How to swap keys and values in a map
Short answer
Walk the pairs and collect a new Map with the key and value swapped:
void main() {
Map<String, Integer> codes = Map.of("DE", 49, "FR", 33, "IT", 39);
Map<Integer, String> byNumber = codes.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey, (a, b) -> a, TreeMap::new));
IO.println(byNumber);
}Output:
{33=FR, 39=IT, 49=DE}Repeated values
If one value belongs to several keys, collect the keys into a list with groupingBy():
void main() {
var cities = new TreeMap<>(Map.of("Berlin", "DE", "Munich", "DE", "Paris", "FR"));
Map<String, List<String>> byCountry = cities.entrySet().stream()
.collect(Collectors.groupingBy(Map.Entry::getValue, TreeMap::new,
Collectors.mapping(Map.Entry::getKey, Collectors.toList())));
IO.println(byCountry);
}Output:
{DE=[Berlin, Munich], FR=[Paris]}With a loop
The same inversion without streams:
void main() {
var colors = new LinkedHashMap<String, String>();
colors.put("red", "#f00");
colors.put("green", "#0f0");
var byHex = new LinkedHashMap<String, String>();
colors.forEach((name, hex) -> byHex.put(hex, name));
IO.println(byHex);
}Output:
{#f00=red, #0f0=green}Common mistake
Using toMap() without a merge function when values repeat. Two equal keys cause an exception:
void main() {
var cities = new TreeMap<>(Map.of("Berlin", "DE", "Munich", "DE"));
var inverted = cities.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
}Output:
Exception in thread "main" java.lang.IllegalStateException: Duplicate key DE (attempted merging values Berlin and Munich)Pass a merge rule as the third argument, for example (a, b) -> a + ", " + b, or use groupingBy().
Functions used in this recipe
- Collectors.toMap() — A collector that builds a map from stream elements.
- Collectors.groupingBy() — A collector that sorts elements into groups that share a key.
- Map.entrySet() — Returns all key and value pairs for iteration.