Back to Blog
Java

Java HashMap Order: Why Iteration Order Is Not Guaranteed

java hashmap order: Understand why HashMap does not guarantee iteration order, how hashing affects it, and when to use LinkedHashMap or TreeMap.

HashMapJava CollectionsLinkedHashMapTreeMapIteration OrderMap Ordering
A visual metaphor of a HashMap with unordered entries scattered across buckets, illustrating unpredictable iteration order.

HashMap is the most commonly used Map implementation in Java, but its iteration order is one of the least understood aspects. If you rely on the order in which entries appear when you iterate over a HashMap, you will eventually be surprised: the order is not guaranteed, and it can change when you insert new entries or when the map is resized. This article explains why java hashmap order is unpredictable, how the internal structure determines it, and which alternatives provide a deterministic ordering when you need one.

How HashMap Stores Entries Internally

HashMap uses an array of buckets, where each bucket is a linked list or a red-black tree (since Java 8 for high-collision scenarios). When you put a key-value pair, the key's hashCode() method produces an integer, and the map reduces that hash to a bucket index using a bitwise operation that depends on the current capacity. The entry is then stored in that bucket.

Because the bucket index is derived from the hash code, the physical placement of an entry has nothing to do with the order in which you inserted it. Two keys with similar hash codes may end up in the same bucket, while keys with very different hash codes may land far apart. The iteration order of a HashMap is essentially the order in which those buckets are visited, and within each bucket, the order in which entries are linked.

Why Iteration Order Is Unpredictable

Several factors make the iteration order of a HashMap effectively arbitrary and subject to change:

  • Hash code values: Different keys produce different hash codes, and the mapping from hash to bucket index is a function of the map's capacity.
  • Capacity and load factor: When the number of entries exceeds capacity * loadFactor, the map resizes to a larger array. This rehashes all entries, recalculating bucket indices, which completely rearranges the iteration order.
  • Collision handling: If multiple keys hash to the same bucket, the order within that bucket depends on the insertion order and whether the bucket is a linked list or a tree. In Java 8+, when a bucket becomes large enough, the linked list is converted to a tree, further altering iteration order.

Because these factors are internal implementation details, you cannot predict the order without knowing the exact hash codes and the map's capacity at every moment. Even the same sequence of insertions can produce different orders across JVM runs if hash codes are randomized (for strings, for example, via String.hashCode() which is deterministic, but for custom objects it depends on the implementation).

What the Java Documentation Says

The official documentation for HashMap is explicit: "This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time." This is not a bug or an oversight; it's a deliberate design choice that allows the implementation to optimize for performance. The lack of order guarantee means the map can use any internal layout that yields fast put, get, and remove operations, without being constrained by the need to preserve insertion or any other order.

When Order Matters: LinkedHashMap and TreeMap

If your code depends on a predictable iteration order, you have two standard alternatives:

  • LinkedHashMap: This class extends HashMap and adds a doubly-linked list that connects entries in insertion order (or access order, if configured). Iterating over a LinkedHashMap yields entries in the order they were inserted, making it a drop-in replacement when you need insertion order without sacrificing the O(1) average complexity of HashMap operations. The only cost is a slightly higher memory footprint and a small overhead for maintaining the linked list.

  • TreeMap: This implementation stores entries in a red-black tree, sorted according to the natural ordering of keys or a custom Comparator. Iteration follows the sorted key order. Operations like put, get, and remove run in O(log n), which is slower than HashMap's average O(1), but the sorted order is guaranteed.

The choice between these two depends on whether you need insertion order or sorted order. If you just need to preserve the order in which you added entries, LinkedHashMap is the right choice. If you need to iterate keys in sorted order, TreeMap is the standard option.

Performance Tradeoffs of Ordered Maps

Choosing an ordered map has real performance implications. HashMap is the fastest general-purpose map because it does no ordering work. LinkedHashMap maintains a linked list of all entries, which adds a constant overhead per entry and a small cost on every insertion, removal, and access (if access order is enabled). For most applications, this overhead is negligible, but in memory-constrained environments or with millions of entries, it can matter.

TreeMap has a more significant cost: every operation is O(log n) due to tree rotations and comparisons. For small maps, the difference is invisible, but for large maps with frequent writes, the logarithmic factor becomes noticeable. Additionally, TreeMap requires keys to be comparable, either via Comparable or a Comparator, which adds a design constraint.

ImplementationIteration Orderput/get/remove ComplexityMemory OverheadWhen to Use
HashMapNone guaranteedO(1) averageLowWhen order doesn't matter
LinkedHashMapInsertion or access orderO(1) averageModerate (linked list)When you need insertion order
TreeMapSorted by keyO(log n)Higher (tree nodes)When you need sorted iteration

Choosing the Right Map for Your Use Case

The decision should be driven by the specific ordering requirement, not by habit. If you are only storing and retrieving values without any need to iterate in a meaningful sequence, HashMap is the best default. If you find yourself writing code that assumes insertion order, either because you are building a cache or a configuration map, switch to LinkedHashMap to make that assumption explicit and reliable.

If you need to process keys in sorted order, TreeMap is the correct choice, but consider whether you could instead sort the keys externally when needed. For a map that is read frequently and modified rarely, sorting on demand with a List might be simpler and more efficient than maintaining a TreeMap.

There is also the option of using HashMap and then sorting the entries when you need to iterate. This is a good approach when the map is large and the iteration with ordering is a rare operation. The sorting cost is O(n log n), which may be acceptable if you only do it occasionally.

Practical Example: Observing Order Changes

The following code demonstrates that the iteration order of a HashMap can change when the map is resized. It inserts a set of entries, prints the order, then inserts enough entries to trigger a resize, and prints the order again.

import java.util.HashMap; import java.util.Map; public class HashMapOrderDemo { public static void main(String[] args) { Map<Integer, String> map = new HashMap<>(); // Initial capacity is 16, load factor 0.75, so resize happens at 12 entries for (int i = 0; i < 10; i++) { map.put(i, "value" + i); } System.out.println("Before resize:"); map.forEach((k, v) -> System.out.print(k + " ")); System.out.println(); // Add more entries to force a resize for (int i = 10; i < 20; i++) { map.put(i, "value" + i); } System.out.println("After resize:"); map.forEach((k, v) -> System.out.print(k + " ")); System.out.println(); } }

On a typical JVM, the output before and after the resize will differ in the sequence of keys. The exact order is not predictable from the code alone; it depends on the hash codes of the Integer keys (which are their numeric values) and the capacity after resizing. This example illustrates why you should never rely on the iteration order of a HashMap in production code.

Compatibility and Maintainability Considerations

When you use HashMap and later change the keys' hashCode() implementation, the iteration order can change even without any resize. This can break code that accidentally depends on order, leading to subtle bugs that are hard to trace. Using LinkedHashMap or TreeMap makes the ordering contract explicit, which improves maintainability because the behavior is documented and stable.

Another subtle issue is that the iteration order of a HashMap is not part of its API contract. If you later switch to a different JVM implementation or a different version of the Java standard library, the order might change even if your code and data are identical. This makes any reliance on order a portability risk.

For these reasons, the safest approach is to decide upfront whether order matters. If it does, choose an ordered map. If it doesn't, document that assumption in your code so that future maintainers do not inadvertently depend on the current, accidental order.

java hashmap order: Practical Usage and Code Examples | RYUSLOG DEV