Как элегантно поменять местами ключи и значения на карте - PullRequest
16 голосов
/ 14 декабря 2010

Я уже знаю, как сделать это трудным путем и заставить его работать - перебирать записи и менять местами «вручную».Но мне интересно, если, как и многие другие задачи, эту задачу можно решить более изящным способом.

Я прочитал этот пост , к сожалению, он не имеет элегантных решений.У меня также нет возможности использовать какие-либо причудливые биографические карты Guava или что-либо вне jdk (стек проекта уже определен).

Я могу предположить, что моя карта является биективной, кстати:

Ответы [ 8 ]

28 голосов
/ 07 февраля 2017
Map<String, Integer> map = new HashMap<>();
Map<Integer, String> swapped = map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
22 голосов
/ 14 декабря 2010

Если у вас нет выбора использовать стороннюю библиотеку, я не считаю следующий код уродливым (хотя некоторые языки сценариев действительно имеют изящные способы сделать это):

//map must be a bijection in order for this to work properly
public static <K,V> HashMap<V,K> reverse(Map<K,V> map) {
    HashMap<V,K> rev = new HashMap<V, K>();
    for(Map.Entry<K,V> entry : map.entrySet())
        rev.put(entry.getValue(), entry.getKey());
    return rev;
}
9 голосов
/ 14 декабря 2010

Стандартная среда выполнения API / Java не предлагает двунаправленную карту, поэтому единственное решение состоит в том, чтобы перебрать все записи и поменять их местами вручную.

Что вы можете сделать, это создать класс-обертку, который содержит две карты и который выполняет двойное put() внутренне, так что у вас есть быстрый просмотр двух данных.

[РЕДАКТИРОВАТЬ] Кроме того, благодаря открытому исходному коду вам не нужно включать стороннюю библиотеку, вы можете просто скопировать нужные классы в ваш собственный проект.

3 голосов
/ 14 декабря 2010

Карты не похожи на списки, которые можно поменять местами, поменяв местами хвостместо для хранения, необходимо построить другую карту.Не существует элегантного способа.

Однако существуют двунаправленные карты.Они могут удовлетворить ваши потребности.Я бы пересмотрел использование сторонних библиотек.

2 голосов
/ 14 декабря 2010

Есть некоторые задания, которые можно упростить до определенного момента и не более. Это может быть один из них!

Если вы хотите выполнить работу с использованием только Java-коллекций apis, тогда грубая сила - это путь - он будет быстрым (если коллекция не огромна) и будет очевидным фрагментом кода.

1 голос
/ 28 сентября 2018

Если бы у вас был доступ к фондам Apache commons-collection, вы могли бы использовать MapUtils.invertMap .

Примечание. Поведение в случае дублирования значений не определено.

(Отвечая на это, так как это первый результат Google для "Java Invert Map").

1 голос
/ 06 октября 2017

Как подсказка для ответа https://stackoverflow.com/a/42091477/8594421

Это работает, только если карта не является HashMap и не содержит повторяющихся значений.

Map<String,String> newMap = oldMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));

выдает исключение

java.lang.IllegalStateException: дубликат ключа

, если существуют значения более одного раза.

Решение:

HashMap<String,String> newMap = new HashMap<>();

for(Map.Entry<String,String> entry : oldMap.entrySet())
        newMap.put(entry.getValue(), entry.getKey());

// Add inverse to old one
oldMap.putAll(newMap);
0 голосов
/ 21 февраля 2019

Это также будет работать для дублированных значений на карте, но не для HashMap в качестве значений.

package Sample;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class Sample {
    public static void main(String[] args) { 
        Map<String,String> map = new HashMap<String,String>(); 
        Map<String, Set<String> > newmap = new HashMap<String, Set<String> >(); 

        map.put("1", "a"); 
        map.put("2", "a"); 
        map.put("3", "b"); 
        map.put("4", "b"); 
        System.out.println("before Reversing \n"+map.toString()); 

        for (Map.Entry<String, String> entry : map.entrySet()) 
        { 
            String oldVal = entry.getValue(); 
            String oldKey = entry.getKey(); 
            Set<String> newVal = null; 

            if (newmap.containsKey(oldVal)) 
            { 
                newVal = newmap.get(oldVal); 
                newVal.add(oldKey); 
            } 
            else 
            { 
                newVal= new HashSet<>(); 
                newVal.add(oldKey); 
            } 
            newmap.put(oldVal, newVal); 
        } 
        System.out.println("After Reversing \n "+newmap.toString()); 
    } 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...