I\'m having a bit of trouble reversing a given map and storing its reversed keys and values into another map. I have a method prototype as follows:
public st
I would first suggest writing a Graph
class which abstracts away the underlying Map
data structure. Of course, this just pushes the implementation to the Graph
interface rather than dealing directly with the Map
interface.
So for now, stick with your map:
Map<String, Set<String>> graph;
Map<String, Set<String>> reverse;
I suggest using Map.entrySet() to get the set of entries from your graph
. Then for each Map.Entry, retrieve the key and value of each one. Next, for each "vertex" in the value Set
, insert the key into the Set
which is associated with the vertex.
This might be more clear if I formatted it similar to Java code rather than English sentences. I hope you get the basic idea. Of course, using a pre-made and pre-tested solution would be preferrable if it fits into your constraints of project.
Pseudocode, but close to real. Just use a Multimap.
Multimap<String, String> ret = Multimaps.newSetMultimap();
for (Entry<String, Set<String>> entry : graph) {
for(String neighbor : entry.getValue()) {
ret.addTo(neighbor, entry.getKey());
}
}
You will need to loop over the entries in your map, and then, since the values are stored in a set, you will need to loop over that set. You will need to check your result map for each key and create a new set whenever a key does not yet exist.
public static Map<String, Set<String>> reverse (Map <String, Set<String>> graph) {
Map<String, Set<String>> result = new HashMap<String, Set<String>>();
for (Map.Entry<String, Set<String>> graphEntry: graph.entrySet()) {
for (String graphValue: graphEntry.getValue()) {
Set<String> set = result.get(graphValue);
if (set == null) {
set = new HashSet<String>();
result.put(graphValue, set);
}
set.add(graphEntry.getKey());
}
}
return result;
}
Here's actual, working, up-to-date code using Guava Multimaps:
SetMultimap<Integer, Integer> graph = HashMultimap.create();
graph.put(1, 2); // add an edge from 1 to 2
SetMultimap<Integer, Integer> inverse = Multimaps.invertFrom(
graph, HashMultimap.<Integer, Integer> create());
(Disclosure: I contribute to Guava.)
But if you can't use third-party libraries, do something like this...
Map<Integer, Set<Integer>> g;
Map<Integer, Set<Integer>> gInverse = new HashMap<Integer, Set<Integer>>();
for (Map.Entry<Integer, Set<Integer>> gAdj : g.entrySet()) {
Integer v = gAdj.getKey();
for (Integer w : gAdj.getValue()) {
Set<Integer> wInverseAdj = gInverse.get(w);
if (wInverseAdj == null) {
gInverse.put(w, wInverseAdj = new HashSet<Integer>());
}
wInverseAdj.add(v);
}
}
Or if you can use Java 8, use this...
map.entrySet().stream()
.flatMap(entryKToVs -> entryKToVs.getValue().stream()
.map(v -> new AbstractMap.SimpleEntry<>(entryKToVs.getKey(), str)))
.collect(groupingBy(Map.Entry::getValue, mapping(Map.Entry::getKey, toList())))