iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Map / HashMap

java.util.Map is the key/value collection interface. HashMap is the workhorse (O(1) ops, no ordering), LinkedHashMap preserves insertion order, TreeMap maintains sorted order with O(log n), and ConcurrentHashMap is the thread-safe one. Pick by the access pattern, not by habit.

HashMap, LinkedHashMap, TreeMap, and modern helpers

EXAMPLE
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.*;

public class MapsDemo {

    public static void main(String[] args) {
        // 1) HashMap — the default
        Map<String, Integer> scores = new HashMap<>();
        scores.put("alice", 90);
        scores.put("bob",   75);

        // putIfAbsent vs merge vs compute — modern, atomic style
        scores.putIfAbsent("carol", 0);          // only set if missing
        scores.merge("alice", 5, Integer::sum);  // add 5; insert if absent
        scores.compute("bob",  (k, v) -> v == null ? 0 : v + 10);

        // getOrDefault — replace the ternary
        int e = scores.getOrDefault("eve", 0);

        System.out.println(scores);

        // 2) Iteration patterns
        scores.forEach((k, v) -> System.out.println(k + " -> " + v));
        for (Map.Entry<String, Integer> e1 : scores.entrySet()) {
            // change only the value via setValue() — avoids re-put cost
            if (e1.getValue() < 80) e1.setValue(80);
        }

        // 3) Immutable Map (Java 9+)
        Map<String, Integer> caps = Map.of("AU", 26_000_000, "NZ", 5_000_000);
        // caps.put(...);   // throws UnsupportedOperationException

        // 4) LinkedHashMap — insertion order preserved (great for LRU when accessOrder=true)
        Map<String, Integer> ordered = new LinkedHashMap<>();
        ordered.put("c", 3); ordered.put("a", 1); ordered.put("b", 2);
        System.out.println(ordered);             // {c=3, a=1, b=2}

        Map<String, Integer> lru = new LinkedHashMap<>(16, 0.75f, true) {
            @Override protected boolean removeEldestEntry(Map.Entry eldest) {
                return size() > 3;                // bound the cache
            }
        };

        // 5) TreeMap — sorted by key, O(log n) ops, range queries
        TreeMap<String, Integer> sorted = new TreeMap<>(scores);
        System.out.println(sorted.firstKey() + " ... " + sorted.lastKey());
        System.out.println(sorted.headMap("c")); // keys < "c"

        // 6) ConcurrentHashMap — safe for concurrent reads + writes
        ConcurrentHashMap<String, Integer> counts = new ConcurrentHashMap<>();
        counts.compute("hits", (k, v) -> v == null ? 1 : v + 1);
        // Bulk parallel scan — uses ForkJoinPool when the map is large
        counts.forEachKey(1L << 12, k -> System.out.println(k));

        // 7) Grouping + counting from a stream — replaces a manual put loop
        List<String> words = List.of("ant", "bee", "ant", "cat", "bee", "ant");
        Map<String, Long> freq = words.stream()
            .collect(Collectors.groupingBy(w -> w, Collectors.counting()));
        System.out.println(freq);                // {ant=3, bee=2, cat=1}

        // 8) Inversion: from { k -> v } to { v -> [k] }
        Map<Integer, List<String>> byScore = scores.entrySet().stream()
            .collect(Collectors.groupingBy(Map.Entry::getValue,
                       Collectors.mapping(Map.Entry::getKey, Collectors.toList())));

        // 9) Map iteration safety — DO NOT mutate the map while iterating
        //    Use Iterator.remove(), or collect keys-to-remove and remove after.
        scores.entrySet().removeIf(en -> en.getValue() < 60);
    }
}

Why it matters

Reach for merge / compute / computeIfAbsent over the get-test-put dance. They are atomic on ConcurrentHashMap, shorter than the if/else version on any map, and they remove the off-by-one bugs in "add 1 to a counter that might be missing" code.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
Map<String, Integer> ages = new HashMap<>();
ages.put("ada", 36);
ages.computeIfAbsent("bo", k -> 28);
for (var e : ages.entrySet()) System.out.println(e.getKey() + "=" + e.getValue());
Try it Yourself »

Discussion

Loading…