Back to results for “Collections”
Java › Collections Framework

How do you choose between HashMap, LinkedHashMap, and TreeMap based on their different ordering guarantees and performance characteristics?

Advanced

Answer

HashMap provides no ordering guarantee whatsoever (iteration order can even change between runs or after resizing), offering the best average-case O(1) performance for get/put/remove; LinkedHashMap maintains insertion order (or optionally access order, useful for implementing an LRU cache) by additionally threading a doubly-linked list through entries, at a small additional memory and performance cost over plain HashMap; TreeMap maintains keys in sorted order (natural ordering or a custom Comparator) using a red-black tree internally, giving O(log n) operations (slower than HashMap's O(1)) but enabling range queries and guaranteed sorted iteration, which neither HashMap nor LinkedHashMap can provide.
// LinkedHashMap configured for LRU eviction behavior
Map<String, String> lruCache = new LinkedHashMap<>(16, 0.75f, true) {
    @Override
    protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
        return size() > 100;  // evict oldest-accessed entry once capacity exceeded
    }
};

// TreeMap for sorted iteration and range queries
TreeMap<Integer, String> sortedMap = new TreeMap<>();
sortedMap.put(3, "c"); sortedMap.put(1, "a"); sortedMap.put(2, "b");
System.out.println(sortedMap.firstKey());  // 1, always sorted
System.out.println(sortedMap.headMap(3));  // entries with keys < 3
Real-world example A simple in-memory LRU cache implementation extends LinkedHashMap with access-order enabled and overrides removeEldestEntry(), leveraging the JDK's built-in linked-list-ordering support rather than hand-implementing LRU eviction logic from scratch with a separate data structure.

Common follow-ups: What's the performance cost of LinkedHashMap's extra linked-list maintenance compared to plain HashMap?;How does TreeMap's red-black tree implementation guarantee O(log n) worst-case (unlike HashMap's amortized-but-not-guaranteed O(1))?