Invert mapping of a Map in Java
This post will discuss how to invert the mapping of a Map in Java. In order words, create a reverse map in Java.
1. Using for loop
You can use a simple for loop to create a reverse map. The idea is to create a new instance of Map<V,K> for a given map of type Map<K,V>. Then use a loop to iterate over the entries of the given map, and insert each entry into the new map in reverse order of its key-value pair.
The following code demonstrates this. Note that the code assumes that the inverse mapping is well-defined, and will fail for any repeated values in the given map. This can be easily handled by placing a conditional check before inserting a pair into the new map.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import java.util.HashMap; import java.util.Map; public class Main { public static void main(String[] args) { Map<String, Integer> hashMap = new HashMap<>(); hashMap.put("A", 1); hashMap.put("B", 2); hashMap.put("C", 3); Map<Integer, String> inverseMap = new HashMap<>(); for (Map.Entry<String, Integer> entry : hashMap.entrySet()){ inverseMap.put(entry.getValue(), entry.getKey()); } System.out.println(inverseMap); } } |
Output:
{1=A, 2=B, 3=C}
2. Using Stream API
We can do better in Java 8 and above, as demonstrated below:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import java.util.HashMap; import java.util.Map; public class Main { public static void main(String[] args) { Map<String, Integer> hashMap = new HashMap<>(); hashMap.put("A", 1); hashMap.put("B", 2); hashMap.put("C", 3); Map<Integer, String> inverseMap = new HashMap<>(); hashMap.forEach((key, value) -> inverseMap.put(value, key)); System.out.println(inverseMap); } } |
Output:
{1=A, 2=B, 3=C}
Here’s another version using the Collectors.toMap() method, which helps accumulate the key-value pairs into a new Map.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { Map<String, Integer> hashMap = new HashMap<>(); hashMap.put("A", 1); hashMap.put("B", 2); hashMap.put("C", 3); Map<Integer, String> inverseMap = hashMap.entrySet().stream() .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); System.out.println(inverseMap); } } |
Output:
{1=A, 2=B, 3=C}
Note that java.lang.IllegalStateException will be thrown if the values in the original map are not unique. This can be handled in two ways:
⮚ 1. Use a merge function
You can provide a merge function to merge values for the duplicate keys, where the old value can take precedence over the new value or vice versa.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { Map<String, Integer> hashMap = new HashMap<>(); hashMap.put("A", 1); hashMap.put("B", 2); hashMap.put("C", 1); Map<Integer, String> inverseMap = hashMap.entrySet().stream() .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey, (oldValue, newValue) -> newValue)); System.out.println(inverseMap); } } |
Output:
{1=C, 2=B}
⮚ 2. Use groupingBy() function
Alternatively, you can use the groupingBy() collector to collect duplicate values into a List, resulting in a MultiMap.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { Map<String, Integer> hashMap = new HashMap<>(); hashMap.put("A", 1); hashMap.put("B", 2); hashMap.put("C", 1); Map<Integer, List<String>> inverseMap = hashMap.entrySet().stream() .collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList()))); System.out.println(inverseMap); } } |
Output:
{1=[A, C], 2=[B]}
3. Using Guava
If you have the Guava library in your project, you can get a bidirectional map BiMap and use its inverse() method. Note that the inverse() method results in a java.lang.IllegalArgumentException on encountering multiple entries with the same value.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import com.google.common.collect.BiMap; import com.google.common.collect.ImmutableBiMap; public class Main { public static void main(String[] args) { BiMap<String, Integer> biMap = ImmutableBiMap.of("A", 1, "B", 2, "C", 3); BiMap<Integer, String> inverseBiMap = biMap.inverse(); System.out.println(inverseBiMap); } } |
Output:
{1=A, 2=B, 3=C}
4. Using Apache Commons Collections
Like Guava library, Apache Commons Collections BidiMap interface, facilitate bidirectional lookups between key and values. To get an inverted bidirectional map, you can use the inverseBidiMap() method. It returns a view of the map where the keys and values are reversed.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import org.apache.commons.collections4.BidiMap; import org.apache.commons.collections4.bidimap.DualHashBidiMap; public class Main { public static void main(String[] args) { BidiMap<String, Integer> bidiMap = new DualHashBidiMap<>(); bidiMap.put("A", 1); bidiMap.put("B", 2); bidiMap.put("C", 3); System.out.println(bidiMap.inverseBidiMap()); } } |
Output:
{1=A, 2=B, 3=C}
When multiple entries with the same value are found, the later key takes precedence over the former.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import org.apache.commons.collections4.BidiMap; import org.apache.commons.collections4.bidimap.DualHashBidiMap; public class Main { public static void main(String[] args) { BidiMap<String, Integer> bidiMap = new DualHashBidiMap<>(); bidiMap.put("A", 1); bidiMap.put("B", 2); bidiMap.put("C", 1); System.out.println(bidiMap.inverseBidiMap()); } } |
Output:
{1=C, 2=B}
Apache Commons Collections also offers the MapUtils.invertMap() method, which returns a new HashMap with the keys of the given map swapped with the values. We should use this method only if the inverse mapping is well-defined. If the given map had the same value mapped to multiple keys, the returned map will contain one of those keys, but the exact key mapped is undefined.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import org.apache.commons.collections4.MapUtils; import java.util.HashMap; import java.util.Map; public class Main { public static void main(String[] args) { Map<String, Integer> hashMap = new HashMap<>(); hashMap.put("A", 1); hashMap.put("B", 2); hashMap.put("C", 3); Map<Integer, String> inverseMap = MapUtils.invertMap(hashMap); System.out.println(inverseMap); } } |
Output:
{1=A, 2=B, 3=C}
That’s all about inverting mapping of a Map in Java.
Thanks for reading.
To share your code in the comments, please use our online compiler that supports C, C++, Java, Python, JavaScript, C#, PHP, and many more popular programming languages.
Like us? Refer us to your friends and support our growth. Happy coding :)