Back to Stream Practice: Collections & Numbers
Q2Question 2 of 11

Sort a Map by key or value: LinkedHashMap to preserve order

Key Concepts
  • entrySet().stream().sorted(comparingByKey()) sorts map entries by key
  • Four-argument toMap(keyMapper, valueMapper, mergeFunction, LinkedHashMap::new) preserves sorted order
  • LinkedHashMap maintains insertion order, so collecting sorted entries preserves the sort
  • HashMap loses sorted order because it uses hash-bucket ordering
  • The merge function (e1, e2) -> e1 is required by the four-arg toMap signature even if duplicates are impossible
  • comparingByValue().reversed() sorts by value descending

Definition

Stream the map's entrySet, sort by key or value, and collect to a LinkedHashMap with the four-argument toMap to preserve the sorted order.
  • entrySet().stream().sorted(comparingByKey()) sorts map entries by their keys.
  • toMap(Entry::getKey, Entry::getValue, mergeFunction, LinkedHashMap::new) collects sorted entries into a LinkedHashMap that preserves insertion order.
  • LinkedHashMap is essential because HashMap uses hash-bucket ordering, which scrambles the sorted order.
  • The merge function (e1, e2) -> e1 handles potential duplicate keys (required by the toMap signature even if impossible).
  • comparingByValue().reversed() sorts entries by value from highest to lowest.

You sort trade symbols by volume (value): NEFT=7, UPI=5, RTGS=3. If you put them in a regular HashMap, the order scrambles: RTGS=3, NEFT=7, UPI=5. LinkedHashMap remembers the order you inserted entries, so the sorted order is preserved.

Understanding the Concepts

Why can't you sort a Map directly?

A HashMap does not maintain any order. A TreeMap maintains key order but cannot be ordered by value. To sort a Map by value or by a custom key order, you must stream the entries, sort them, and collect into a LinkedHashMap.

How do you sort by key?

JAVA
package com.bank.analytics;

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

public class SortMapDemo {
    public static void main(String[] args) {
        Map<String, Long> txnCounts = Map.of(
            "NEFT", 7L, "UPI", 5L, "RTGS", 3L, "IMPS", 4L);

        // Sort by KEY ascending
        Map<String, Long> byKey = txnCounts.entrySet().stream()
            .sorted(Map.Entry.comparingByKey())
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                Map.Entry::getValue,
                (e1, e2) -> e1,
                LinkedHashMap::new));

        System.out.println("By key: " + byKey);
    }
}
TEXT
By key: {IMPS=4, NEFT=7, RTGS=3, UPI=5}

How do you sort by value descending?

JAVA
// Sort by VALUE descending
Map<String, Long> byValue = txnCounts.entrySet().stream()
    .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
    .collect(Collectors.toMap(
        Map.Entry::getKey,
        Map.Entry::getValue,
        (e1, e2) -> e1,
        LinkedHashMap::new));

System.out.println("By value desc: " + byValue);
TEXT
By value desc: {NEFT=7, UPI=5, IMPS=4, RTGS=3}

Why does HashMap lose the sorted order?

JAVA
// WRONG: without LinkedHashMap, order is lost
Map<String, Long> broken = txnCounts.entrySet().stream()
    .sorted(Map.Entry.comparingByKey())
    .collect(Collectors.toMap(
        Map.Entry::getKey,
        Map.Entry::getValue));  // default HashMap!

// Result might be: {UPI=5, RTGS=3, NEFT=7, IMPS=4} -- random!

The two-argument toMap creates a HashMap by default. HashMap uses hash buckets, which scramble entry order. The four-argument toMap with LinkedHashMap::new preserves the insertion order, which after sorting is the sorted order.

How is this different from TreeMap?

| Map Type | Order | Sort By |
|----------|-------|---------|
| HashMap | No order | N/A |
| TreeMap | Sorted by KEY | Keys only (natural or custom comparator) |
| LinkedHashMap | Insertion order | Any order you insert (after stream sort) |

TreeMap automatically sorts by key but cannot sort by value. For value-based sorting, you must use the stream-sort-to-LinkedHashMap pattern.

What about the merge function?

The merge function (e1, e2) -> e1 is required by the four-argument toMap. It handles duplicate keys. When sorting an existing Map's entries, duplicates are impossible (Map keys are unique), but the API requires it.

What should a senior engineer know?

  • LinkedHashMap has slightly higher memory overhead than HashMap (it maintains a doubly-linked list of entries). For most use cases, this overhead is negligible.
  • For read-heavy sorted maps that do not change, consider an unmodifiable LinkedHashMap: Collections.unmodifiableMap(sortedLinkedHashMap).
  • If you only need sorted keys, use TreeMap directly without the stream-sort-collect pattern.
  • The explicit type parameter Map.Entry.comparingByValue() is often needed to help the compiler infer types when chaining .reversed().

Visual Overview

DIAGRAM
  Map<String, Long>: {NEFT=7, UPI=5, RTGS=3, IMPS=4}
       │
       ▼
  entrySet().stream()
       │
       ▼
  sorted(comparingByValue().reversed())
  [NEFT=7, UPI=5, IMPS=4, RTGS=3]
       │
       ▼
  collect(toMap(..., LinkedHashMap::new))
       │
       ▼
  LinkedHashMap: {NEFT=7, UPI=5, IMPS=4, RTGS=3}
  (insertion order = sorted order = preserved!)

Key Takeaway

Sorting a Map by key or value uses entrySet().stream().sorted(comparingByKey()) or comparingByValue(), then collecting to a LinkedHashMap with the four-argument Collectors.toMap. The LinkedHashMap preserves insertion order, which after sorting is the sorted order. Collecting into a regular HashMap loses the sorted order because HashMap uses hash-bucket ordering.

The four-argument toMap requires a merge function even when duplicates are impossible (Map entries have unique keys by definition). The merge function (e1, e2) -> e1 satisfies the API requirement.

At National Bank of India, the operations dashboard sorts transaction types by volume: NEFT (7), UPI (5), IMPS (4), RTGS (3). The LinkedHashMap preserves this ranking for display.

Remember one sentence: sort the entrySet stream, then collect to LinkedHashMap to preserve the sorted order that HashMap would scramble.

---

Share
Use ← → arrow keys to navigate