HashMap
Reviewed & published by Brayan K
An ArrayList finds items by position. But what if you want to find a person's phone number by their name? A HashMap stores key→value pairs and looks any value up by its key, instantly — like a real dictionary or phone book.
Part of the free Java course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
- Creating a HashMap of key→value pairs
- put, get, remove, and size
- getOrDefault to avoid null
- containsKey and containsValue
- Iterating with entrySet and keySet
- The classic word-count tally pattern
1️⃣ Keys and Values
A HashMap holds pairs. Each pair has a key (what you look up by) and a value (what you get back). Keys are unique; values can repeat.
💡 Analogy: A real dictionary maps a word (key) to its definition (value). You don't scan every page — you jump straight to the word. A HashMap does the same: get("Alice") goes directly to Alice's entry without checking everyone else.
You declare two types in the angle brackets — the key type and the value type. Both must be objects, so use wrapper classes for primitives:
import java.util.HashMap;
HashMap<String, String> phoneBook = new HashMap<>(); // name -> number
HashMap<String, Integer> ages = new HashMap<>(); // name -> age
HashMap<Integer, String> idToName = new HashMap<>(); // id -> name2️⃣ The Core Methods
| Method | What it does |
|---|---|
| put(k, v) | Add the pair, or overwrite if k exists |
| get(k) | Value for k, or null if absent |
| getOrDefault(k, d) | Value for k, or d if absent |
| containsKey(k) | Is there an entry for key k? |
| containsValue(v) | Does any entry hold value v? |
| remove(k) | Delete the entry for k |
| size() | Number of pairs |
| keySet() | All keys (for looping) |
| entrySet() | All key/value pairs (for looping) |
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
// A HashMap stores KEY -> VALUE pairs. Here: name -> phone number.
HashMap<String, String> phoneBook = new HashMap<>();
phoneBook.put("Alice", "555-0101"); // add or update
phoneBook.put("Bob", "555-0202");
phoneBook.put("Carol", "555-0303");
// Look up by key — instant, no scanning the whole collection
System.out.println("Alice -> " + phoneBook.get("Alice"));
// get() returns null for a missing key
System.out.println("Dave -> " + phoneBook.get("Dave"));
// getOrDefault avoids the null
System.out.println("Dave -> " + phoneBook.getOrDefault("Dave", "unknown"));
// Membership checks
System.out.println("Has Bob? " + phoneBook.containsKey("Bob"));
System.out.println("Size: " + phoneBook.size());
// put with an existing key OVERWRITES the old value
phoneBook.put("Alice", "555-9999");
System.out.println("Alice now -> " + phoneBook.get("Alice"));
phoneBook.remove("Bob");
System.out.println("After remove, has Bob? " + phoneBook.containsKey("Bob"));
}
}3️⃣ Looping Over a HashMap
To visit every pair, loop over entrySet() and read each entry's key and value. To visit only keys, loop over keySet().
for (Map.Entry<String, Integer> e : map.entrySet()) {
System.out.println(e.getKey() + " = " + e.getValue());
}import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> stock = new HashMap<>();
stock.put("apples", 12);
stock.put("bananas", 5);
stock.put("cherries", 30);
// Loop over every key/value pair
for (Map.Entry<String, Integer> entry : stock.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// Loop over just the keys
int totalItems = 0;
for (String fruit : stock.keySet()) {
totalItems += stock.get(fruit);
}
System.out.println("Total items in stock: " + totalItems);
}
}4️⃣ The Tally Pattern (Counting Things)
The single most common HashMap pattern is counting occurrences: words in a sentence, votes per candidate, clicks per page. The trick is getOrDefault:
counts.put(word, counts.getOrDefault(word, 0) + 1);
// ↑ key ↑ current count (0 first time) + 1The first time a key is seen, getOrDefault returns the default 0, so the count becomes 1. Every later time, it returns the existing count and adds one. Clean and bug-free, with no separate "is this the first time?" check.
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
// CLASSIC use case: count how many times each word appears.
String text = "the cat sat on the mat the cat ran";
String[] words = text.split(" ");
HashMap<String, Integer> counts = new HashMap<>();
for (String word : words) {
// getOrDefault makes the "first time we've seen it" case clean:
counts.put(word, counts.getOrDefault(word, 0) + 1);
}
for (Map.Entry<String, Integer> e : counts.entrySet()) {
System.out.println(e.getKey() + " -> " + e.getValue());
}
// Find the most frequent word
String top = "";
int best = 0;
for (Map.Entry<String, Integer> e : counts.entrySet()) {
if (e.getValue() > best) {
best = e.getValue();
top = e.getKey();
}
}
System.out.println("Most common: '" + top + "' (" + best + " times)");
}
}import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
// 🎯 YOUR TURN — replace each ___ using the hint beside it.
Map<String, Integer> stock = new HashMap<>();
// 1) Store a value under a key. The same call also OVERWRITES.
stock.___("bolt", 40); // 👉 replace ___ with put
stock.put("nut", 120);
stock.put("washer", 0);
// 2) Read it back by key.
System.out.println("Bolts: " + stock.___("bolt")); // 👉 replace ___ with get
// 3) A key that is missing gives null — unless you supply a fallback.
System.out.println("Screws: " + stock.___("screw", 0)); // 👉 replace ___ with getOrDefault
// 4) Present at all? Note that "present" and "not zero" differ.
System.out.println("Has washer? " + stock.___("washer")); // 👉 replace ___ with containsKey
stock.put("bolt", 35); // same key: replaces 40
// 5) Add to whatever is already there, in one call.
stock.___("nut", 5, Integer::sum); // 👉 replace ___ with merge
stock.remove("washer");
System.out.println("Bolts now: " + stock.get("bolt"));
System.out.println("Nuts now: " + stock.get("nut"));
System.out.println("Size: " + stock.size());
// A HashMap has NO order, so sort the keys before printing them.
for (String key : new java.util.TreeSet<>(stock.keySet())) {
System.out.println(" " + key + " -> " + stock.get(key));
}
}
}🧩 Reorder Challenge
Reorder these lines to store one age and look it up.
System.out.println(ages.get("Sam"));
ages.put("Sam", 28);
HashMap<String, Integer> ages = new HashMap<>();HashMap<String, Integer> ages = new HashMap<>();
ages.put("Sam", 28);
System.out.println(ages.get("Sam"));Why: The map must exist before you put into it, and the pair must be stored before get can retrieve it. If you reversed put and get, the lookup would print null. Output: 28.
🧠 Quick Recall
1. What does this print?
HashMap<String, Integer> m = new HashMap<>();
m.put("a", 1);
m.put("a", 5);
System.out.println(m.size());1. Keys are unique, so the second put("a", 5) overwrites the value rather than adding a new entry.
2. What does this print?
HashMap<String, Integer> m = new HashMap<>();
System.out.println(m.getOrDefault("x", -1));-1. The key "x" is absent, so getOrDefault returns the supplied default instead of null.
3. What does this print?
HashMap<String, Integer> m = new HashMap<>();
m.put("k", m.getOrDefault("k", 0) + 1);
m.put("k", m.getOrDefault("k", 0) + 1);
System.out.println(m.get("k"));2. First put: 0 + 1 = 1. Second put: 1 + 1 = 2. That's the tally pattern running twice.
Common Beginner Mistakes
- ❌ Calling a method on a null get(): map.get("missing").length() crashes. Use getOrDefault or containsKey.
- ❌ Primitive type arguments: HashMap<String, int> is illegal — use HashMap<String, Integer>.
- ❌ Expecting an order: HashMap iteration order is unpredictable. Use LinkedHashMap or TreeMap if order matters.
- ❌ Forgetting Map import: using Map.Entry needs import java.util.Map;.
- ❌ Duplicate keys "lost": putting the same key twice overwrites — it doesn't keep both.
📋 Quick Reference
| Method | Description | Example |
|---|---|---|
| new HashMap<>() | Create an empty map | HashMap<String, Integer> m = new HashMap<>(); |
| put(k, v) | Add pair, or overwrite if k exists | m.put("a", 1) |
| get(k) | Value for k, or null if absent | m.get("a") |
| getOrDefault(k, d) | Value for k, or d if absent | m.getOrDefault("z", 0) |
| containsKey(k) | Is there an entry for key k? | m.containsKey("a") |
| containsValue(v) | Does any entry hold value v? | m.containsValue(1) |
| remove(k) | Delete the entry for k | m.remove("a") |
| size() | Number of key-value pairs | m.size() |
| keySet() | All keys (for looping) | for (String k : m.keySet()) |
| values() | All values (for looping) | m.values() |
| entrySet() | All key-value pairs | for (Map.Entry<K,V> e : m.entrySet()) |
| e.getKey() / e.getValue() | Read a pair while iterating | e.getKey() |
| getOrDefault(k,0)+1 | Tally / count pattern | m.put(w, m.getOrDefault(w,0)+1) |
| merge(k, 1, Integer::sum) | Alternative tally one-liner | m.merge(w, 1, Integer::sum) |
🎉 Lesson Complete!
You now command Java's most useful collection for lookups: put and get pairs, dodge null with getOrDefault, check membership with containsKey, iterate with entrySet/keySet, and count things with the tally pattern.
Practice quiz
What does a HashMap store?
- Only values, by index
- Key-value pairs
- Unique values only
- Sorted numbers
Answer: Key-value pairs. A HashMap stores key-value pairs and looks values up by key.
What happens when you put the same key twice?
- It adds a second entry
- It overwrites the old value
- It throws an exception
- It ignores the new value
Answer: It overwrites the old value. Keys are unique; a second put with the same key overwrites the value.
After m.put('a',1); m.put('a',5); what is m.size()?
- 0
- 1
- 2
- 5
Answer: 1. Both puts use key 'a', so there is just one entry — size is 1.
What does get(key) return for a key that is not present?
- 0
- An empty string
- null
- It throws
Answer: null. get returns null for a missing key, which can cause a NullPointerException if used carelessly.
Which method returns a fallback instead of null for a missing key?
- get
- getOrDefault
- containsKey
- orElse
Answer: getOrDefault. getOrDefault(key, fallback) returns the fallback when the key is absent.
Which key type is illegal for a HashMap?
- String
- Integer
- int
- Character
Answer: int. Keys must be objects; use the wrapper Integer, not the primitive int.
How do you loop over every key-value pair?
- for (x : map)
- for (Map.Entry<K,V> e : map.entrySet())
- for (i = 0; i < map.size; i++)
- map.forEachKey()
Answer: for (Map.Entry<K,V> e : map.entrySet()). Iterate map.entrySet() and read e.getKey()/e.getValue().
Is a HashMap's iteration order guaranteed?
- Yes, insertion order
- Yes, sorted order
- No, it can look random
- Yes, reverse order
Answer: No, it can look random. HashMap order is not guaranteed; use LinkedHashMap for insertion order or TreeMap for sorted.
Which line correctly implements the word-count tally pattern?
- counts.add(word)
- counts.put(word, counts.getOrDefault(word, 0) + 1)
- counts.increment(word)
- counts.put(word, counts.get(word) + 1)
Answer: counts.put(word, counts.getOrDefault(word, 0) + 1). getOrDefault(word, 0) + 1 handles the first-time case cleanly without a null check.
Which class keeps keys in sorted order?
- HashMap
- LinkedHashMap
- TreeMap
- ArrayMap
Answer: TreeMap. TreeMap stores keys in sorted order.
Continue this course
- Previous: ArrayList
- Next: Checkpoint: Java Basics — Combine input, collections and formatting in a build challenge — then a quiz
- Quick reference: Java cheat sheet › Collections
Frequently asked questions
What is a HashMap and when should I use one?
A HashMap stores key-value pairs and lets you look up a value by its key almost instantly, no matter how big the map is. Use it whenever you want to associate one thing with another: a username to a user object, a product code to a price, a word to its count. If you only need a list of values without keys, use an ArrayList instead.
What happens if I put the same key twice?
Keys are unique. Calling put with a key that already exists overwrites the old value with the new one rather than adding a second entry. So map.put("x", 1) followed by map.put("x", 2) leaves the map with a single entry x -> 2. If you need multiple values per key, store a list as the value: HashMap of String to a List.
Why does get() return null, and how do I avoid NullPointerExceptions?
get(key) returns null when the key is not present. If you then call a method on that null you get a NullPointerException. Avoid it with getOrDefault(key, fallback), which returns your fallback when the key is missing, or guard with containsKey(key) before calling get. getOrDefault is especially handy for counting and tallying.
How do I loop over a HashMap, and is the order guaranteed?
Iterate the pairs with for (Map.Entry<K,V> e : map.entrySet()) and call e.getKey() and e.getValue(); or loop map.keySet() for just the keys. The order is NOT guaranteed and can look random, because entries are placed by hash code. If you need keys in insertion order use a LinkedHashMap, and for sorted keys use a TreeMap.
What types can I use for keys and values?
Both must be reference types (objects), so use wrapper classes for primitives: HashMap<String, Integer>, not HashMap<String, int>. Keys should have sensible equals and hashCode methods; String, Integer, and most built-in types already do. Values can be anything, including another collection like an ArrayList or even another HashMap.