Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Java Collectors.toMap: preserve encounter order with LinkedHashMap

Last updated: 5 Oct 20264 min read
tutorial
AdvancedBy AITrove Editorial

The basic toMap collector makes no map-order promise; pass a LinkedHashMap supplier when input order belongs in the output.

Choose order at the collector boundary

A receipt summary displayed in arrival order should not depend on whichever map implementation a collector happens to return. The four-argument toMap overload accepts a map supplier, so the result can preserve first insertion order while duplicate keys use a declared merge rule.

Updating an existing key in a default insertion-order LinkedHashMap does not move it to the end. The program retains the first position of RC-47 even though its amount is replaced. LinkedHashMap behavior explains when an access-order map would differ.

Keep parallel assumptions separate

Encounter order and merge behavior should be specified before using a parallel stream. A side-effecting merge function is unsafe; an associative value merge is easier to reason about. Parallel encounter order covers terminal behavior.

Working program

Java
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class ReceiptArrivalIndex {
    static final class Receipt {
        final String id;
        final int cents;
        Receipt(String id, int cents) {
            this.id = id;
            this.cents = cents;
        }
    }
    public static void main(String[] args) {
        Map<String, Integer> centsByReceipt = Arrays.asList(
                new Receipt("RC-47", 1200), new Receipt("RC-82", 3400),
                new Receipt("RC-47", 1500)).stream().collect(Collectors.toMap(
                receipt -> receipt.id,
                receipt -> receipt.cents,
                (earlier, later) -> later,
                LinkedHashMap::new));
        centsByReceipt.forEach((id, cents) ->
                System.out.println(id + "=" + cents));
    }
}

Output

Output
RC-47=1500
RC-82=3400

Cost and ownership

Expected collection is O(n) time and O(k) map space for k unique receipts, with extra link fields per entry compared with a plain hash map. Explicit ordering costs memory; use it only when a caller relies on stable presentation order.

Common Mistakes

  • Do not assume HashMap or basic toMap preserves arrival order.
  • Do not expect updating a key to move it in an insertion-order LinkedHashMap.
  • Do not make the merge callback depend on external mutable state.

Read next

Java LinkedHashMap: encounter order and a bounded cache model, Java Collectors.toMap: choose a duplicate-key rule, stream parallel encounter order, Java HashMap: keys, collisions, and update operations.

java
streams
collectors-tomap-order
Storage details