Java HashMap vs LinkedHashMap: Key Differences
java hashmap vs linkedhashmap: Understand the differences between Java HashMap and LinkedHashMap, including iteration order, performance, and when to use each.
When you need to store key-value pairs in Java, the choice between HashMap and LinkedHashMap often comes down to whether iteration order matters. Both implement the Map interface, but they differ in how they maintain internal structure and what guarantees they offer about the order of entries. The java hashmap vs linkedhashmap decision affects memory footprint, iteration behavior, and even the ability to build certain algorithms like LRU caches.
The Core Difference: Order Guarantee
The most important distinction is that HashMap makes no promise about the order in which entries appear when you iterate over the map. It uses a hash table that distributes entries based on their hash codes, and the resulting order can change when the map is resized or when entries are added or removed. LinkedHashMap, on the other hand, maintains a doubly linked list running through all of its entries. This list defines a predictable iteration order, which by default is the order in which keys were inserted.
Map<String, Integer> hashMap = new HashMap<>(); hashMap.put("apple", 1); hashMap.put("banana", 2); hashMap.put("cherry", 3); System.out.println("HashMap: " + hashMap.keySet()); // Output is unpredictable, e.g., [banana, apple, cherry] Map<String, Integer> linkedHashMap = new LinkedHashMap<>(); linkedHashMap.put("apple", 1); linkedHashMap.put("banana", 2); linkedHashMap.put("cherry", 3); System.out.println("LinkedHashMap: " + linkedHashMap.keySet()); // Always [apple, banana, cherry]
The HashMap output above is illustrative; the actual order depends on hash codes and internal capacity. The LinkedHashMap output is deterministic as long as the insertion order is not modified.
How HashMap Stores Entries
HashMap stores entries in an array of buckets, where each bucket is a linked list or tree (when collisions become frequent). When you insert a key-value pair, the key's hashCode() method determines the bucket index. If two keys land in the same bucket, they are stored as a chain. This design gives average O(1) time for put, get, and remove, but it also means that iterating over the map requires traversing the bucket array and then each chain. The order you see is essentially the order of the bucket array plus the order within each chain, which is not meaningful to your application.
Because HashMap does not track insertion order, it can be more memory-efficient than LinkedHashMap. It only needs to store the array of buckets and the entry objects themselves. There is no extra linked list structure to maintain.
How LinkedHashMap Adds Order
LinkedHashMap extends HashMap and adds a doubly linked list that connects all entries in the order they were inserted. Each entry in the map also contains references to the previous and next entry in this list. When you iterate over the map, the iteration follows this linked list, giving you a consistent order without needing to sort or copy the keys.
You can also configure LinkedHashMap to iterate in access order rather than insertion order. This is done through the constructor that takes accessOrder as a boolean parameter. When set to true, every time you call get or put on an existing key, that entry is moved to the end of the linked list. This behavior is the foundation for building an LRU (Least Recently Used) cache.
Map<String, Integer> lruCache = new LinkedHashMap<>(16, 0.75f, true); lruCache.put("a", 1); lruCache.put("b", 2); lruCache.get("a"); // Moves "a" to the end System.out.println(lruCache.keySet()); // [b, a]
Here, the third constructor argument true enables access order. The first two arguments are the initial capacity and load factor, which are inherited from HashMap. This example shows that after calling get("a"), the order changes so that a appears last, reflecting its recent access.
Performance and Memory Tradeoffs
The extra linked list in LinkedHashMap adds a small constant overhead to every entry. Each entry must store two additional references (previous and next), which increases memory usage compared to HashMap. The time complexity for basic operations remains O(1) on average, but the constant factors are slightly higher because maintaining the linked list requires updating pointers on every insertion, removal, and (in access-order mode) on every access.
For most applications, this overhead is negligible. The real cost appears when you have millions of entries and memory is tight. In that case, HashMap is the leaner choice. However, if you need deterministic iteration order, LinkedHashMap saves you from the cost of sorting keys or maintaining a separate list manually.
It is important to note that neither implementation is synchronized. If you use them in a multi-threaded environment, you must handle external synchronization or use Collections.synchronizedMap.
Choosing Between HashMap and LinkedHashMap
Use HashMap when you do not care about iteration order. This is the common case for lookups, caching (when order is irrelevant), and any scenario where you only need fast key-based access. Use LinkedHashMap when you need to preserve the order in which entries were added, or when you need access-order semantics for an LRU cache.
A practical example of the latter is a simple cache that evicts the least recently used entry when it reaches a size limit. You can override removeEldestEntry to enforce the policy:
class SimpleLRUCache<K, V> extends LinkedHashMap<K, V> { private final int maxSize; public SimpleLRUCache(int maxSize) { super(16, 0.75f, true); this.maxSize = maxSize; } @Override protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { return size() > maxSize; } }
This cache automatically removes the oldest entry (the one least recently accessed) when the map exceeds maxSize. The accessOrder=true constructor flag is what makes this work, because it ensures that the linked list reflects access recency.
Common Misconceptions About Order
A frequent misunderstanding is that HashMap has a predictable order if you use it with certain keys. That is not true. The order depends on the hash function, the initial capacity, the load factor, and the history of additions and removals. Even if you add the same keys in the same order, the iteration order can change if the map is resized or if you use a different Java version. Relying on HashMap order is a bug waiting to happen.
Another misconception is that LinkedHashMap is always slower than HashMap. While it has a slightly higher constant overhead, the algorithmic complexity is the same. In many real-world applications, the difference is not measurable. The choice should be based on whether you need the order guarantee, not on micro-optimization.
When Order Matters in Real Code
Consider a configuration system that loads properties from a file and must preserve the order in which the properties were defined. If you use HashMap, the order is lost, and the output when you write the properties back to a file will be arbitrary. LinkedHashMap preserves the original order, making the round-trip predictable.
Another case is building a user interface where you need to display menu items in the order they were added. Storing them in a LinkedHashMap lets you iterate in that order without an extra sort step. In contrast, using HashMap would require you to keep a separate List of keys to remember the order, which duplicates data and adds complexity.
Finally, the access-order mode of LinkedHashMap is not just for caches. It can be used to track recently viewed items, to implement a most-recently-used list, or to build a simple history mechanism. The key is that the map itself maintains the order, so you do not have to update a separate structure on every access.
Understanding the java hashmap vs linkedhashmap tradeoff is not about choosing a "better" map; it is about matching the data structure to the requirement. If order is irrelevant, HashMap gives you a leaner implementation. If order matters, LinkedHashMap provides a built-in mechanism that is both efficient and easy to use.