javahashmapjava-11

Java HashMap iteration order - behavior seems consistent despite documentation stating otherwise


I'm learning about HashMaps in Java and I'm confused about the iteration order. The documentation states that HashMap doesn't guarantee any specific iteration order, but in my simple test, the order seems to remain consistent:

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. Java 11 Docs

import java.util.HashMap;

public class HashMapDemo {
    public static void main(String[] args) {
        HashMap<String, String> dishes = new HashMap<>();

        // Adding more elements with complex keys
        dishes.put("dish-1234", "Pho");
        dishes.put("dish-5678", "Spicy Beef Noodle Soup");
        dishes.put("dish-9012", "Broken Rice");
        dishes.put("dish-3456", "Banh Mi");
        dishes.put("dish-7890", "Hu Tieu");
        dishes.put("dish-2345", "Mi Quang");
        dishes.put("dish-6789", "Crab Noodle Soup");
        dishes.put("dish-0123", "Rolled Rice Cake");

        System.out.println("First time:");
        dishes.forEach((id, name) -> System.out.println(id + ": " + name));

        // Create new HashMap with same data
        HashMap<String, String> dishes2 = new HashMap<>();
        dishes2.putAll(dishes);

        System.out.println("\nSecond time (New HashMap):");
        dishes2.forEach((id, name) -> System.out.println(id + ": " + name));
    }
}

Output:

First time:
dish-7890: Hu Tieu
dish-3456: Banh Mi
dish-2345: Mi Quang
dish-1234: Pho
dish-0123: Rolled Rice Cake
dish-5678: Spicy Beef Noodle Soup
dish-9012: Broken Rice
dish-6789: Crab Noodle Soup

Second time (New HashMap):
dish-7890: Hu Tieu
dish-3456: Banh Mi
dish-2345: Mi Quang
dish-1234: Pho
dish-0123: Rolled Rice Cake
dish-5678: Spicy Beef Noodle Soup
dish-9012: Broken Rice
dish-6789: Crab Noodle Soup

I understand that if I need guaranteed order, I should use LinkedHashMap or TreeMap, but I'm trying to understand the actual behavior of HashMap. I read some documentation talk about re-size and re-hashing, maybe it's too hard to understand for me.

I also read some post say this problem, but I can not re-produce

How can I understand this?


Solution

  • Behavior may vary

    trying to understand the actual behavior of HashMap

    You are trying to understand the internal implementation details of HashMap. Don’t.

    Whatever behavior you may observe, that behavior may vary.

    The Javadoc is the contract

    If the Javadoc says you cannot count on a particular order, then do not depend on a particular order.

    If the Javadoc does not promise thread-safety, then do not expect thread-safety.

    The Javadoc is the formal contract, the agreement between you and the implementation programmers. Do not make assumptions or use your intuition. What you read in the Javadoc describes the expected behavior. Anything beyond the Javadoc may exist, may not exist, or may vary, but should never be expected by you.

    SequencedMap

    For a particular order, use an implementation of SequencedMap. Implementations bundled with Java: ConcurrentSkipListMap, LinkedHashMap, and TreeMap. To learn about the Sequenced Collections API added to Java 21, read JEP 431, and see excellent talk by Stuart Marks.

    Java offers two other ordered map interfaces: NavigableMap (Java 6+) and SortedMap (Java 2+), both implemented by two of those three classes named above: ConcurrentSkipListMap and TreeMap.

    Consider using TreeMap first, if thread-safety is not a concern. Very large amounts of data may perform better with ConcurrentSkipListMap.

    Diagram of Map class hierarchy in Java 21+, by Basil Bourque, 2024-11

    Mermaid coding:

    ---
    title: Java Map hierarchy
    ---
    classDiagram
        Map <|-- SequencedMap
        SequencedMap <|-- SortedMap
        SortedMap <|-- NavigableMap
        NavigableMap <|-- ConcurrentNavigableMap
        NavigableMap <|.. TreeMap : implements
        ConcurrentNavigableMap <|.. ConcurrentSkipListMap : implements
        SequencedMap <|.. LinkedHashMap : implements
        class Map {
            <<interface>>
        }
        class SequencedMap {
            <<interface>>
        }
        class NavigableMap {
            <<interface>>
        }
        class SortedMap {
            <<interface>>
        }
        class ConcurrentNavigableMap {
            <<interface>>
        }
        class TreeMap {
        }
        class ConcurrentSkipListMap {
        }
        class LinkedHashMap {
        }
    

    Third-parties

    You may find third-party implementations of ordered maps, such as in Google Guava or Eclipse Collections.

    Curiosity

    If curiosity drives you to learn about the implementation details of HashMap, learn the basic concepts such as at Wikipedia, then study the open source code on GitHub.