Streaming a Map

Streams · lesson 27 of 42 · 4 min read

Filter, sort and rebuild maps through entrySet, and keep the order you asked for.

Open this lesson in the learning hub

Key points

  • A Map has no stream() of its own. Stream keySet(), values() or entrySet() instead.
  • entrySet() is the useful one, because the key and the value stay together through the whole pipeline.
  • Map.Entry.comparingByValue() and comparingByKey() are ready made comparators for sorting.
  • Sorting alone is not enough: collect into a LinkedHashMap or the order is thrown away again.
  • The four argument toMap takes a merge function and a map factory, which is how you avoid duplicate key exceptions.
  • Do not modify the map you are streaming. Build a new one and swap it in.

Example

import java.util.*;
import java.util.stream.*;

public class Main {
    public static void main(String[] args) {
        Map<String, Integer> stock = new LinkedHashMap<>();
        stock.put("apple", 12);
        stock.put("fig", 0);
        stock.put("pear", 7);

        System.out.println("keys    : " + stock.keySet().stream().sorted().toList());
        System.out.println("total   : " + stock.values().stream().mapToInt(Integer::intValue).sum());

        // entrySet() is the workhorse: the key and the value stay together.
        System.out.println("in stock: " + stock.entrySet().stream()
                .filter(e -> e.getValue() > 0)
                .map(e -> e.getKey() + "=" + e.getValue())
                .toList());

        // Flip a map. The merge function decides what happens on a duplicate key.
        Map<Integer, String> flipped = stock.entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey, (a, b) -> a, TreeMap::new));
        System.out.println("flipped : " + flipped);

        // Sort by value, then keep that order by collecting into a LinkedHashMap.
        Map<String, Integer> ranked = stock.entrySet().stream()
                .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                        (a, b) -> a, LinkedHashMap::new));
        System.out.println("ranked  : " + ranked);

        // Building a map from a list is the other direction.
        System.out.println("built   : " + Stream.of("ada", "grace")
                .collect(Collectors.toMap(n -> n, String::length, (a, b) -> a, TreeMap::new)));
    }
}

Stream entrySet, and collect into a LinkedHashMap when the new order matters.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Streams course, and every lesson in it is listed on the Streams contents page.