How to Invert a Map in Java – 如何在Java中倒置一个地图

最后修改: 2022年 2月 22日

1. Overview


In this quick article, we’ll take a look at how to invert a Map in Java. The idea is to create a new instance of Map<V, K> for a given map of type Map<K, V>. In addition, we’ll also see how to handle the case where there are duplicate values present in the source map.

在这篇文章中,我们将看看如何在Java中反转Map。我们的想法是为一个给定的Map<V, K>类型的地图创建一个新的Map<K, V>的实例。此外,我们还将看到如何处理源地图中存在重复值的情况。

Please refer to our other article to learn more about the HashMap class itself.


2. Defining the Problem


Let’s consider we have a Map with a few Key-Value pairs:


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

The original Map would store the items like:


{first=1, second=2}

Instead, we’d like to invert the keys into values and vice versa into a new Map object. The result would be:


{1=first, 2=second}

3. Using a Traditional for Loop


First, let’s see how to invert a Map using a for loop:


public static <V, K> Map<V, K> invertMapUsingForLoop(Map<K, V> map) {
    Map<V, K> inversedMap = new HashMap<V, K>();
    for (Entry<K, V> entry : map.entrySet()) {
        inversedMap.put(entry.getValue(), entry.getKey());
    return inversedMap;

Here, we’re iterating through the entrySet() of the Map object. After that, we add the original Value as a new Key and the original Key as the new Value into the inversedMap object. In other words, we copy the contents of the map by replacing the keys with values and values with keys. Further, this is suitable for Java versions before 8, though we should note that this approach only works if the source map’s values are unique.

在这里,我们正在迭代Map对象的entrySet() 。之后,我们将原来的Value作为新的Key加入到inversedMap对象中,并将原来的Key作为新的Value换句话说,我们通过用值替换键,用键替换值来复制地图的内容。此外,这适用于 8 之前的 Java 版本,不过我们应该注意到,这种方法只有在源地图的值是唯一的情况下才有效

4. Using Stream API to Invert a Map

4. Using Stream API to Invert a Map

Java 8 provides convenient methods from the Stream API to invert a Map in a more functional style. Let’s have a look at a few of them.

Java 8从Stream API中提供了方便的方法,以更实用的风格反转Map。让我们来看看其中的几个。

4.1. Collectors.toMap()


We can use Collectors.toMap() if we don’t have any duplicate values in the source map:

我们可以使用Collectors.toMap() 如果我们在源地图中没有任何重复的值

public static <V, K> Map<V, K> invertMapUsingStreams(Map<K, V> map) {
    Map<V, K> inversedMap = map.entrySet()
        .collect(Collectors.toMap(Entry::getValue, Entry::getKey));
    return inversedMap;

First, the entrySet() is converted into a stream of objects. Subsequently, we used Collectors.toMap() to collect the Key and Value into the inversedMap object.


Let’s consider that the source map contains duplicate values. In such cases, we can use a mapping function to apply custom rules to the input elements:


public static <K, V> Map<V, K> invertMapUsingMapper(Map<K, V> sourceMap) {
    return sourceMap.entrySet()
            Collectors.toMap(Entry::getValue, Entry::getKey, (oldValue, newValue) -> oldValue) 

In this method, the last argument to Collectors.toMap() is a mapping function. Using this, we can customize which key should be added in case there are duplicates. In the above example, we retain the first value as key if the source map contains duplicate values. However, we can retain only one key if the values repeat.


4.2. Collectors.groupingBy()


Sometimes, we may need all the keys even if the source map contains duplicate values. Alternatively, Collectors.groupingBy() provides better control for handling duplicate values.


For instance, let’s consider we have the following KeyValue pair:


{first=1, second=2, two=2}

Here, the value “2” is repeated twice for different keys. In these cases, we can use the groupingBy() method to implement a cascaded “group by” operation on the Value objects:

这里,值 “2 “在不同的键上重复了两次。在这些情况下,我们可以使用groupingBy() 方法来实现对Value对象的级联 “分组 “操作。

private static <V, K> Map<V, List<K>> invertMapUsingGroupingBy(Map<K, V> map) {
    Map<V, List<K>> inversedMap = map.entrySet()
        .collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList())));
    return inversedMap;

To explain a bit, the Collectors.mapping() function performs a reduction operation on the values associated with the given key using the specified collector. The groupingBy() collector collects duplicate values into a List, resulting in a MultiMap. The output now will be:


{1=[first], 2=[two, second]}

5. Conclusion


In this article, we quickly reviewed several built-in ways to invert a HashMap with examples. Also, we saw how to handle duplicate values when we invert a Map object.


Meanwhile, a few external libraries provide additional features on top of the Map interface. We’ve previously demonstrated how to invert a Map using Google Guava BiMap and Apache BidiMap.

同时,一些外部库在Map接口之上提供了额外的功能。我们之前已经演示了如何使用Google Guava BiMapApache BidiMap来反转一个Map

As always, the code for these examples is available over on GitHub.