Sorting a map by value, and top-N

Collections · lesson 36 of 42 · 4 min read

Rank entries by value, and keep the largest few without sorting the whole thing.

Open this lesson in the learning hub

Key points

  • A TreeMap sorts by key. Ranking by value means sorting the entries and rebuilding the map.
  • The idiom: stream entrySet(), sort with Map.Entry.comparingByValue(), collect into a LinkedHashMap.
  • Only a LinkedHashMap keeps that order. Collecting into a HashMap throws the sort straight away.
  • For the top N of a million rows a size-N min-heap wins: O(n log N) time and N entries of memory.
  • Offer into a PriorityQueue, then poll() whenever its size passes N — the smallest is always the one dropped.
  • Break ties on the key with thenComparing, or equal values come back in an arbitrary order.

Example

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

public class Main {
    public static void main(String[] args) {
        Map<String, Integer> votes = new LinkedHashMap<>();
        votes.put("java", 12);
        votes.put("go", 7);
        votes.put("rust", 12);
        votes.put("perl", 2);
        votes.put("ruby", 9);

        Comparator<Map.Entry<String, Integer>> byValueDesc =
                Map.Entry.<String, Integer>comparingByValue().reversed()
                        .thenComparing(Map.Entry.comparingByKey());

        Map<String, Integer> ranked = votes.entrySet().stream()
                .sorted(byValueDesc)
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                        (a, b) -> a, LinkedHashMap::new));
        System.out.println("sorted by value   : " + ranked);

        Map<String, Integer> lost = votes.entrySet().stream()
                .sorted(byValueDesc)
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        System.out.println("into a HashMap    : " + lost + "   (the order was thrown away)");

        PriorityQueue<Map.Entry<String, Integer>> top =
                new PriorityQueue<>(Map.Entry.comparingByValue());
        for (Map.Entry<String, Integer> e : votes.entrySet()) {
            top.offer(e);
            if (top.size() > 3) top.poll();
        }
        List<String> best = top.stream().sorted(byValueDesc)
                .map(e -> e.getKey() + "=" + e.getValue())
                .toList();
        System.out.println("top 3 by min-heap : " + best);
        System.out.println("heap ever held    : 3 entries, never the whole map");
        System.out.println("TreeMap sorts keys: " + new TreeMap<>(votes).keySet() + "   (never values)");
    }
}

Sort the entries when you want them all in order, heap them when you only want the top few.

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 Collections course, and every lesson in it is listed on the Collections contents page.