Вопрос:

Reverse HashMap keys and values in Java

java hashmap

82053 просмотра

8 ответа

841 Репутация автора

It's a simple question, I have a simple HashMap of which i want to reverse the keys and values.

HashMap<Character, String> myHashMap = new HashMap<Character, String>();
myHashMap.put('a', "test one");
myHashMap.put('b', "test two");

and I want to create a new HashMap in which i put the opposites.

HashMap<String, Character> reversedHashMap = new HashMap<String, Character>();
e.g. Keys "test one" & "test two" and values 'a' & 'b'.
Автор: Ken Источник Размещён: 05.12.2013 10:44

Ответы (8)


2 плюса

7650 Репутация автора

Iterate through the list of keys and values, then add them.

HashMap<String, Character> reversedHashMap = new HashMap<String, Character>();
for (String key : myHashMap.keySet()){
    reversedHashMap.put(myHashMap.get(key), key);
}
Автор: hichris123 Размещён: 05.12.2013 10:48

109 плюса

73132 Репутация автора

Решение

They all are unique, yes

If you're sure that your values are unique you can iterate over the entries of your old map .

Map<String, Character> myNewHashMap = new HashMap<>();
for(Map.Entry<Character, String> entry : myHashMap.entrySet()){
    myNewHashMap.put(entry.getValue(), entry.getKey());
}

Alternatively, you can use a Bi-Directional map like Guava provides and use the inverse() method :

BiMap<Character, String> myBiMap = HashBiMap.create();
myBiMap.put('a', "test one");
myBiMap.put('b', "test two");

BiMap<String, Character> myBiMapInversed = myBiMap.inverse();

As is out, you can also do it this way :

Map<String, Integer> map = new HashMap<>();
map.put("a",1);
map.put("b",2);

Map<Integer, String> mapInversed = 
    map.entrySet()
       .stream()
       .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey))

Finally, I added my contribution to the proton pack library, which contains utility methods for the Stream API. With that you could do it like this:

Map<Character, String> mapInversed = MapStream.of(map).inverseMapping().collect();
Автор: Alexis C. Размещён: 05.12.2013 10:50

2 плюса

15577 Репутация автора

To answer your question on how you can do it, you could get the entrySet from your map and then just put into the new map by using getValue as key and getKey as value.

But remember that keys in a Map are unique, which means if you have one value with two different key in your original map, only the second key (in iteration order) will be kep as value in the new map.

Автор: A4L Размещён: 05.12.2013 10:51

3 плюса

841 Репутация автора

I wrote a simpler loop that works too (note that all my values are unique):

HashMap<Character, String> myHashMap = new HashMap<Character, String>();
HashMap<String, Character> reversedHashMap = new HashMap<String, Character>();

for (char i : myHashMap.keySet()) {
    reversedHashMap.put(myHashMap.get(i), i);
}
Автор: Ken Размещён: 06.12.2013 12:14

20 плюса

221 Репутация автора

Apache commons collections library provides a utility method for inversing the map. You can use this if you are sure that the values of myHashMap are unique

org.apache.commons.collections.MapUtils.invertMap(java.util.Map map)

Sample code

HashMap<String, Character> reversedHashMap = MapUtils.invertMap(myHashMap) 
Автор: Riju Thomas Размещён: 29.09.2015 06:24

1 плюс

1191 Репутация автора

private <A, B> Map<B, A> invertMap(Map<A, B> map) {
    Map<B, A> reverseMap = new HashMap<>();
    for (Map.Entry<A, B> entry : map.entrySet()) {
        reverseMap.put(entry.getValue(), entry.getKey());
    }
    return reverseMap;
}

It's important to remember that put replaces the value when called with the same key. So if you map has two keys with the same value only one of them will exist in the inverted map.

Автор: Mark Hetherington Размещён: 23.04.2018 10:01

6 плюса

132 Репутация автора

If the values are not unique, the safe way to inverse the map is by using java 8's groupingBy function

Map<String, Integer> map = new HashMap<>();
map.put("a",1);
map.put("b",2);

Map<Integer, List<String>> mapInversed = 
map.entrySet()
   .stream()
   .collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList())))
Автор: mob Размещён: 16.05.2018 03:53

0 плюса

111 Репутация автора

Tested with below sample snippet, tried with MapUtils, and Java8 Stream feature. It worked with both cases.

public static void main(String[] args) {
    Map<String, String> test = new HashMap<String, String>();
    test.put("a", "1");
    test.put("d", "1");
    test.put("b", "2");
    test.put("c", "3");
    test.put("d", "4");
    test.put("d", "41");

    System.out.println(test);

    Map<String, String> test1 = MapUtils.invertMap(test);

    System.out.println(test1);

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

    System.out.println(mapInversed);
}

Output:
{a=1, b=2, c=3, d=41}
{1=a, 2=b, 3=c, 41=d}
{1=a, 2=b, 3=c, 41=d}
Автор: Deepak Arora Размещён: 17.08.2018 04:10
Вопросы из категории :
32x32