Difference Between HashMap and TreeMap in Java
HashMap and TreeMap both implement Map and store unique keys mapped to values, but they are built very differently:
HashMapis a hash table: O(1) average operations and no ordering.TreeMapis a red-black tree: keys are always sorted, operations take O(log n), and it supports range and nearest-key queries throughNavigableMap.
1. Comparison Table
| Aspect | HashMap | TreeMap |
|---|---|---|
| Ordering | None guaranteed | Sorted by key (natural order or Comparator) |
| Data structure | Array of buckets (lists/trees) | Red-black tree |
| get / put / remove | O(1) average | O(log n) |
| Key equality | hashCode() + equals() | compareTo() or compare() |
| Null keys | One allowed | Not allowed (natural ordering) |
| Null values | Allowed | Allowed |
| Interfaces | Map | NavigableMap, SortedMap, SequencedMap |
| Range / nearest queries | No | floorKey, ceilingEntry, headMap, subMap… |
| Memory | Table plus entries | Tree nodes (parent, left, right, colour) |
| Thread-safe alternative | ConcurrentHashMap | ConcurrentSkipListMap |
2. Sorted Keys and Navigation
import java.util.*;
public class SortedKeys {
public static void main(String[] args) {
Map<String, Integer> hash = new HashMap<>();
TreeMap<String, Integer> tree = new TreeMap<>();
for (String w : "spring java kafka docker java aws spring java".split(" ")) {
hash.merge(w, 1, Integer::sum);
tree.merge(w, 1, Integer::sum);
}
System.out.println("HashMap : " + hash + " <- no order");
System.out.println("TreeMap : " + tree + " <- keys sorted");
// NavigableMap methods: only TreeMap
System.out.println("firstKey / lastKey : " + tree.firstKey() + " / " + tree.lastKey());
System.out.println("ceilingKey(\"b\") : " + tree.ceilingKey("b"));
System.out.println("headMap(\"java\") : " + tree.headMap("java"));
System.out.println("descendingMap : " + tree.descendingMap());
TreeMap<String, Integer> byLength = new TreeMap<>(Comparator.comparing(String::length).thenComparing(Comparator.reverseOrder()));
byLength.putAll(hash);
System.out.println("custom comparator : " + byLength);
}
}
HashMap : {spring=2, java=3, kafka=1, aws=1, docker=1} <- no order
TreeMap : {aws=1, docker=1, java=3, kafka=1, spring=2} <- keys sorted
firstKey / lastKey : aws / spring
ceilingKey("b") : docker
headMap("java") : {aws=1, docker=1}
descendingMap : {spring=2, kafka=1, java=3, docker=1, aws=1}
custom comparator : {aws=1, java=3, kafka=1, spring=2, docker=1}
3. Range Lookups and Null Keys
floorEntry finds the greatest key less than or equal to a value, perfect for slabs, price bands and time-based lookups:
import java.util.*;
public class RangeQueries {
public static void main(String[] args) {
// Illustrative tax slabs: lower bound -> rate
TreeMap<Integer, Integer> slabs = new TreeMap<>(Map.of(0, 0, 300_000, 5, 700_000, 10, 1_000_000, 15, 1_200_000, 20));
for (int income : new int[] {250_000, 850_000, 1_500_000})
System.out.println("income " + income + " -> rate " + slabs.floorEntry(income).getValue() + "%");
try {
new TreeMap<String, Integer>().put(null, 1);
} catch (NullPointerException e) {
System.out.println("TreeMap null key -> NullPointerException");
}
Map<String, Integer> hash = new HashMap<>();
hash.put(null, 1);
System.out.println("HashMap null key ok: " + hash.containsKey(null));
}
}
income 250000 -> rate 0% income 850000 -> rate 10% income 1500000 -> rate 20% TreeMap null key -> NullPointerException HashMap null key ok: true
4. When to Use Which
HashMap: fast lookups by key when order does not matter. This is the default choice.TreeMap: when you need keys sorted, ranges (between two keys), or the nearest key below or above a value.LinkedHashMap: when you need insertion order with hash-map speed.
If you only need sorted output once, filling a HashMap and sorting its entries at the end can be faster than maintaining a TreeMap.
5. Summary
HashMap: O(1), unordered, one null key allowed.TreeMap: O(log n), sorted keys, no null keys, rich navigation API.TreeMapcompares keys withcompareTo/comparator;HashMapuseshashCode/equals.- Neither is thread-safe; use
ConcurrentHashMaporConcurrentSkipListMap.
Related Tutorials
Frequently Asked Questions (FAQ)
Q1. What is the main difference between HashMap and TreeMap?
HashMap is unordered with O(1) operations; TreeMap keeps keys sorted with O(log n) operations.
Q2. Which is faster?
HashMap for individual lookups and inserts. TreeMap is better when you need ordered traversal or range queries.
Q3. Can TreeMap have a null key?
No, not with natural ordering; put(null, v) throws NullPointerException. Null values are allowed.
Q4. What data structure does TreeMap use?
A red-black tree, a self-balancing binary search tree that guarantees O(log n) operations.
Q5. How does TreeMap compare keys?
With the keys' compareTo method, or a Comparator passed to the constructor.
Q6. What happens if keys are not Comparable?
Without a comparator, TreeMap throws ClassCastException when you insert them.
Q7. How do I sort a HashMap by key?
new TreeMap<>(hashMap), or sort the entry set with a stream.
Q8. How do I sort a map by value?
Stream the entries with sorted(Map.Entry.comparingByValue()) and collect into a LinkedHashMap.
Q9. What is NavigableMap?
An interface for sorted maps with navigation methods like floorKey, ceilingKey, headMap, tailMap and descendingMap.
Q10. Are they thread-safe?
No. Use ConcurrentHashMap or ConcurrentSkipListMap for concurrent access.
Q11. Which uses more memory?
Usually TreeMap per entry, because nodes hold three references and a colour; HashMap also has its bucket array.
Q12. How do I get keys in descending order?
Use treeMap.descendingMap() or a TreeMap built with Comparator.reverseOrder().
Q13. Can HashMap maintain sorted order?
No. Use TreeMap for sorted keys or LinkedHashMap for insertion order.
Q14. What is the worst-case lookup time in HashMap?
O(log n) since Java 8, when a crowded bucket is converted to a tree; before that it was O(n).
Q15. Does TreeMap use equals?
No, it uses comparison. If compareTo is inconsistent with equals, the map may treat distinct keys as the same.
Q16. What does floorEntry return?
The entry with the greatest key less than or equal to the given key, or null if none exists.
Q17. How do I get a range of keys?
subMap(fromKey, toKey), headMap(toKey) or tailMap(fromKey), which return live views.
Q18. Are iterators fail-fast in both?
Yes. Structural changes during iteration (other than via the iterator) throw ConcurrentModificationException.
Q19. When is TreeMap the better choice?
For leaderboards, schedules, event timelines, price bands and any problem that needs ordered keys or nearest-key lookups.
Q20. Is this asked in interviews?
Yes. Explain the data structures, time complexities, ordering, null handling and navigation methods.