Encodera

Thanks for reading!

Donate to the site — we work hard for you.

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

Thanks for reading!

Donate to the site — we work hard for you.