在Java中反向HashMap键和值

Reverse HashMap keys and values in Java

这是一个简单的问题,
我有一个简单的HashMap,我想反转其键和值。

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

我想创建一个新的HashMap,在其中放置相反的内容。

1
2
HashMap<String, Character> reversedHashMap = new HashMap<String, Character>();
e.g. Keys"test one" &"test two" and values 'a' & 'b'.


They all are unique, yes

如果您确定自己的值是唯一的,则可以遍历旧地图的条目。

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

另外,您可以使用Guava提供的双向地图,并使用inverse()方法:

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

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

随着java-8的发布,您也可以通过以下方式进行操作:

1
2
3
4
5
6
7
8
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))

最后,我对质子包装库做出了贡献,该库包含Stream API的实用程序方法。这样,您可以这样做:

1
Map<Character, String> mapInversed = MapStream.of(map).inverseMapping().collect();


Apache Commons Collections库提供了一种用于反转地图的实用方法。如果您确定myHashMap的值是唯一的,则可以使用此方法

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

样例代码

1
HashMap<String, Character> reversedHashMap = MapUtils.invertMap(myHashMap)


如果值不是唯一的,则逆映射的安全方法是使用Java 8的groupingBy函数

1
2
3
4
5
6
7
8
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())))

我写了一个更简单的循环,也可以工作(请注意,我所有的值都是唯一的):

1
2
3
4
5
6
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);
}

1
2
3
4
5
6
7
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;
}

重要的是要记住,put在用相同的键调用时会替换该值。因此,如果您的地图具有两个具有相同值的键,则倒置地图中将只存在其中一个。


要回答有关如何执行此操作的问题,可以从地图中获取entrySet,然后通过将getValue用作key并将getKey用作value来放入新地图。

但是请记住,映射中的键是唯一的,这意味着,如果您的原始映射中有一个值带有两个不同的键,则只有第二个键(按迭代顺序)将作为新映射中的值保留。


遍历键和值的列表,然后添加它们。

1
2
3
4
HashMap<String, Character> reversedHashMap = new HashMap<String, Character>();
for (String key : myHashMap.keySet()){
    reversedHashMap.put(myHashMap.get(key), key);
}


在下面的示例代码段中进行了测试,并在MapUtils和Java8 Stream功能中进行了尝试。它适用于两种情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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}