JavaHashMap

HashMap

HashMap is the most commonly used implementation of the Map interface. It's backed by a hash table, giving it O(1) average time for the two operations you use most: get() and put().

Basic HashMap usage

Java
import java.util.HashMap;
import java.util.Map;

Map<String, Double> prices = new HashMap<>();
prices.put("coffee", 3.50);
prices.put("tea", 2.75);

System.out.println(prices.get("coffee"));
System.out.println(prices);
3.5
{coffee=3.5, tea=2.75}
Why equals() and hashCode() Matter
A HashMap finds the bucket for a key by calling hashCode() on it, then uses equals() to confirm an exact match once it's narrowed things down to that bucket. Both String and the boxed number types (Integer, Long, and so on) already implement these correctly, which is why they work as keys without any extra effort. The full contract between these two methods is covered on the Object Class page — this page focuses on why it matters specifically for HashMap.
Custom key classes need equals() and hashCode()
If you use your own class as a HashMap key and don't override equals() and hashCode(), HashMap falls back to the defaults inherited from Object — reference identity. That means two objects that are logically "the same" (say, two separate Point objects both holding x=1, y=2) will be treated as two different keys, and get() will fail to find a value you know you put in. This is one of the most common real-world Java bugs involving collections.

A broken key class — missing equals()/hashCode()

Java
import java.util.HashMap;
import java.util.Map;

class Point {
    int x, y;
    Point(int x, int y) { this.x = x; this.y = y; }
    // no equals() or hashCode() override!
}

Map<Point, String> labels = new HashMap<>();
labels.put(new Point(1, 2), "origin-ish");

System.out.println(labels.get(new Point(1, 2))); // prints null!
null
The lookup fails because new Point(1, 2) in the get() call is a different object from the one used in put(), and without an overridden equals()/hashCode() pair, HashMap has no way to know they should be considered equal. Overriding both methods consistently (typically with an IDE-generated implementation or Java records) fixes this immediately.
No Ordering Guarantee
Just like HashSet, a HashMap makes no promises about the order its entries come back in when you iterate it. That order depends on internal hash bucket placement and can shift as the map grows. If you need a predictable order, look at TreeMap (sorted) or LinkedHashMap (insertion order) — both covered on the next page.
getOrDefault() and putIfAbsent()
Two convenience methods make everyday HashMap code both shorter and safer to write: getOrDefault(), which returns a fallback value instead of null when a key is missing, and putIfAbsent(), which only inserts a value if the key isn't already present.

Counting word occurrences with getOrDefault()

Java
import java.util.HashMap;
import java.util.Map;

Map<String, Integer> wordCounts = new HashMap<>();
String[] words = {"cat", "dog", "cat", "bird", "dog", "cat"};

for (String word : words) {
    wordCounts.put(word, wordCounts.getOrDefault(word, 0) + 1);
}

System.out.println(wordCounts);
{bird=1, cat=3, dog=2}

putIfAbsent() avoids overwriting existing values

Java
import java.util.HashMap;
import java.util.Map;

Map<String, String> defaults = new HashMap<>();
defaults.put("theme", "dark");

defaults.putIfAbsent("theme", "light"); // no-op, "theme" already set
defaults.putIfAbsent("language", "en"); // inserted, key was missing

System.out.println(defaults);
{language=en, theme=dark}
Null Keys and Values
Note
HashMap allows one null key and any number of null values. This is a HashMap-specific allowance, not a rule that holds across every Map implementation — TreeMap, for instance, throws a NullPointerException if you try to use a null key, because it needs to compare keys to keep them sorted.

HashMap tolerates a null key

Java
import java.util.HashMap;
import java.util.Map;

Map<String, String> settings = new HashMap<>();
settings.put(null, "fallback");
settings.put("mode", null);

System.out.println(settings.get(null));
System.out.println(settings.get("mode"));
fallback
null

Aspect

HashMap

Average get/put time

O(1)

Ordering

None — unpredictable

Null keys

One allowed

Null values

Any number allowed

Requires

Correct equals()/hashCode() on key type

Tip
When defining a custom key class, prefer a Java record where possible — records generate correct equals() and hashCode() implementations automatically, eliminating this entire category of bug.
  • O(1) average get/put, backed by a hash table

  • Custom keys must correctly implement equals() and hashCode()

  • No ordering guarantee on iteration

  • getOrDefault() and putIfAbsent() simplify common patterns

  • Allows one null key and multiple null values