Как поменять местами значения и ключи arrayMap в Java
У меня возникли некоторые проблемы с реверсированием данной карты и сохранением ее реверсированных ключей и значений в другой карте. У меня есть прототип метода следующим образом:
public static Map<String, Set<String>> reverse (Map <String, Set<String>> graph);
Итак, если у меня есть примеры ключей для направленного графа, такие что:
{c -> arraySet{f, e}}
{b -> d}
{a -> arraySet{c, b}}
{d -> g}
{e -> d}
{f -> arraySet{g, d}}
Мне нужно эффективно перевернуть этот граф так, чтобы вместо b - > d у меня был d - > b.
Я думаю, что все, что для этого требуется, - это обмен значениями и ключами в исходном графике и добавление их в обратную карту. Я полагаю, что могу повторить через каждый набор значений для данного ключа на графике, а затем и хранить их в списке.
К сожалению, у меня возникли проблемы с реализацией этого и обдумыванием. Я был бы очень признателен, если бы вы подтолкнули меня в правильном направлении.
4 ответов:
Вам нужно будет сделать цикл над записями в вашей карте, а затем, поскольку значения хранятся в наборе, вам нужно будет сделать цикл над этим набором. Вам нужно будет проверить свою карту результатов для каждого ключа и создать новый набор, когда ключ еще не существует.
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; }
Вот фактический, рабочий, актуальный код с использованием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());(раскрытие: я делаю вклад в гуаву.)
Но если вы не можете использовать сторонние библиотеки, сделайте что-нибудь вроде этого...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); } }Или, если вы можете использовать Java 8, используйте это...
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())))
Псевдокод, но близкий к реальному. Просто используйте Multimap .
Multimap<String, String> ret = Multimaps.newSetMultimap(); for (Entry<String, Set<String>> entry : graph) { for(String neighbor : entry.getValue()) { ret.addTo(neighbor, entry.getKey()); } }
Я бы сначала предложил написать класс
Graph, который абстрагирует основную структуру данныхMap. Конечно, это просто подталкивает реализацию к интерфейсуGraph, а не непосредственно к интерфейсуMap.Так что пока придерживайтесь своей карты:
Map<String, Set<String>> graph; Map<String, Set<String>> reverse;Я предлагаю использовать карту.entrySet () , чтобы получить набор записей из вашего
graph. Затем для каждой карты .Запись , получить ключ и значение каждого из них. Далее, для каждой "вершины" в значенииSet, вставьте ключ вSet, который связан с вершиной.Это может быть более ясно, если я отформатирую его подобно Java-коду, а не английским предложениям. Надеюсь, вы поняли основную идею. Конечно, использование заранее подготовленного и протестированного решения было бы предпочтительнее, если оно вписывается в ваши ограничения проекта.
Comments