How to swap arrayMap values and keys in Java

久未见 提交于 2019-12-01 10:48:33

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())))

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());
  }
}

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.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!