SECTION 1
Historical Context & Motivation
Imagine you have a list of a thousand student names and you need to look up each student's grade instantly. If you stored all those names in a plain array, you'd have to scan through potentially every element to find the one you want. This is the fundamental problem that hash tables were invented to solve: providing near-instant lookups by associating a key (like a student's name) with a value (like their grade) using a clever mathematical trick called hashing.
1953 • Hash Tables Conceived
1995 • Java 1.0 Introduces Hashtable
1998 • Java 1.2 — The Collections Framework
2004 • Java 5 Adds Generics
2014 • Java 8 Performance Improvements
Today, HashMap is one of the most commonly used classes in all of Java programming. Whether you need to count how many times each word appears in an essay, store a phone book of contacts, or track scores in a game, HashMap gives you a clean and efficient way to do it. The central question this lesson addresses is: how do we use HashMap to store key–value pairs and count frequencies of items?
SECTION 2
Core Principles & Definitions
A HashMap is a data structure that stores data as key–value pairs. You can think of it like a real-world dictionary: you look up a word (the key) and instantly get its definition (the value). Unlike an array where you access elements by index number, a HashMap lets you access values by any type of key — a String, an Integer, or other object types.
Key–Value Pairs
Hash Function
O(1) Average Access
No Guaranteed Order
Null Keys & Values
KEY TAKEAWAY
SECTION 3
Visual Explanation — How HashMap Works Internally
The diagram above illustrates the three-stage journey every key–value pair takes inside a HashMap. First, the key (like "Alice") is fed into a hash function that produces a numeric index. That index determines which bucket in the underlying array will store the entry. When two keys happen to hash to the same bucket index — called a collision — Java links them together in a chain. Despite the occasional collision, most lookups go straight to the right bucket in constant time.
SECTION 4
How HashMap Works — Essential Methods
Working with a HashMap in Java revolves around a handful of core methods. You create one by specifying the types for the key and value inside angle brackets (generics). Here's how each essential operation works under the hood.
Creating a HashMap
To declare and instantiate a HashMap that maps Strings to Integers, you write: HashMap<String, Integer> map = new HashMap<>();. The first type in the angle brackets is the key type and the second is the value type. Note that you must use wrapper classes (Integer, not int) because generics don't support primitive types.
Core Methods Reference
| Method | Description | Example |
|---|---|---|
put(key, value) | Adds or updates a key–value pair in the map. | map.put("Alice", 92); |
get(key) | Returns the value mapped to the given key, or null if not found. | int score = map.get("Alice"); |
getOrDefault(key, default) | Returns the value for the key, or the default value if the key is absent. | map.getOrDefault("Zoe", 0); |
containsKey(key) | Returns true if the map contains the specified key. | map.containsKey("Bob"); |
remove(key) | Removes the entry for the given key and returns its value. | map.remove("Charlie"); |
size() | Returns the number of key–value pairs currently in the map. | int n = map.size(); |
keySet() | Returns a Set of all keys, useful for iterating over the map. | for (String k : map.keySet()) |
Essential HashMap methods you'll use most often
The Frequency Counting Pattern
One of the most common uses of HashMap is frequency counting — tallying how many times each item appears in a collection. The pattern follows a simple recipe: loop through your data, and for each item, either set its count to 1 (if it's new) or increment the existing count by 1. In code, this looks like: map.put(item, map.getOrDefault(item, 0) + 1);. This single line is the heart of frequency counting with HashMap.
Pro Tip
getOrDefault(key, 0) method was added in Java 8 and eliminates the need for an if-else check. Before Java 8, you had to write: if (map.containsKey(item)) { map.put(item, map.get(item) + 1); } else { map.put(item, 1); }. The modern one-liner is much cleaner.SECTION 5
Common HashMap Patterns & Iteration
Beyond basic put and get, HashMap supports several powerful patterns that come up frequently in programming challenges and real-world code. Let's visualize the frequency counting pattern step by step, then explore iteration techniques.
getOrDefault finds an existing entry — it returns the current count, which is then incremented by 1.Iterating Over a HashMap
After building a HashMap, you often need to loop through it. There are three main approaches. You can iterate over keySet() to get just the keys, over values() to get just the values, or over entrySet() to access both the key and value together. The entrySet() approach is generally preferred when you need both key and value, because it avoids an extra lookup. For example: for (Map.Entry<String, Integer> entry : map.entrySet()) { System.out.println(entry.getKey() + ": " + entry.getValue()); }
SECTION 6
Worked Example — Word Frequency Counter
Let's walk through a complete program that reads an array of words and counts how many times each word appears. This is one of the most practical applications of HashMap you'll encounter.
Counting Word Frequencies in a Sentence
- 1
Step 1 — Set Up the Data and the Map
Start with your input data and create an empty HashMap. The keys will be Strings (the words) and the values will be Integers (the counts).String[] words = {"the", "cat", "sat", "on", "the", "mat", "the", "cat"};Then create the map:HashMap<String, Integer> freq = new HashMap<>();freq is an empty HashMap: {} - 2
Step 2 — Loop Through the Array and Count
Use a for-each loop to process each word. For every word, call getOrDefault to check the current count (defaulting to 0 if the word hasn't been seen), add 1, and store the updated count back in the map.for (String word : words) { freq.put(word, freq.getOrDefault(word, 0) + 1); }After the loop: {the=3, cat=2, sat=1, on=1, mat=1} - 3
Step 3 — Print the Results
Iterate over the entrySet to display each word and its frequency.for (Map.Entry<String, Integer> entry : freq.entrySet()) { System.out.println(entry.getKey() + " appears " + entry.getValue() + " time(s)"); }Output: the appears 3 time(s), cat appears 2 time(s), sat appears 1 time(s), on appears 1 time(s), mat appears 1 time(s) - 4
Step 4 — Find the Most Frequent Word
To find which word appears most often, loop through the entries and track the maximum count.String maxWord = ""; int maxCount = 0; for (Map.Entry<String, Integer> entry : freq.entrySet()) { if (entry.getValue() > maxCount) { maxCount = entry.getValue(); maxWord = entry.getKey(); } }Most frequent word: "the" with count 3
Import Reminder
import java.util.HashMap; and import java.util.Map; at the top of your file. Without these imports, Java won't recognize the HashMap or Map.Entry classes.SECTION 7
HashMap vs. Other Data Structures
HashMap is incredibly useful, but it isn't always the right tool. Understanding when to choose it over alternatives is a key skill. Let's compare HashMap with other common Java data structures to understand its strengths and limitations.
| Feature | HashMap | TreeMap | Array / ArrayList |
|---|---|---|---|
| Lookup speed | O(1) average — constant time | O(log n) — slower but sorted | O(n) by value, O(1) by index |
| Insertion speed | O(1) average | O(log n) | O(1) at end, O(n) at beginning |
| Order preserved? | No — entries are unordered | Yes — sorted by key | Yes — insertion order |
| Key–value pairs? | Yes — native support | Yes — native support | No — single values only |
| Null keys allowed? | Yes — one null key | No — throws exception | N/A — no key concept |
| Best for | Fast lookups, counting | Sorted data, range queries | Indexed access, sequential data |
Comparison of common Java data structures for storage and retrieval
WHEN TO USE HASHMAP
SECTION 8
Connections to Advanced Topics
The HashMap patterns you're learning now form the foundation for many advanced programming concepts. As you progress in computer science, you'll encounter variations and extensions of these ideas that build directly on your understanding of key–value storage and frequency counting.
| What You Know Now | Where It Leads |
|---|---|
| HashMap<String, Integer> for counting | Databases use similar hash-based indexes to find records instantly among millions of rows |
| Hash functions converting keys to indices | Cryptographic hash functions (SHA-256) secure passwords and blockchain technology |
| Collision handling with chaining | Open addressing and cuckoo hashing — alternative strategies studied in data structures courses |
| HashMap<String, List<String>> for grouping | MapReduce and distributed computing frameworks (Hadoop, Spark) for processing big data |
| Frequency counting pattern | Natural language processing, spam detection, and recommendation algorithms |
How HashMap concepts connect to advanced computer science
In AP Computer Science and beyond, you'll also encounter HashSet, which uses the same hashing mechanism as HashMap but stores only keys (no values). It's perfect for tracking unique items — like finding all distinct words in a text. You might also explore ConcurrentHashMap, a thread-safe version designed for multi-threaded applications where multiple parts of a program read and write to the same map simultaneously. The core principles of hashing, constant-time access, and key–value pairing remain the same across all of these.
SECTION 9
Practice Problems
Question 1: CONCEPTUAL
Show answer
Question 2: BASIC CALCULATION
HashMap<String, Integer> map = new HashMap<>(); map.put("x", 10); map.put("y", 20); map.put("x", 30); map.put("z", 40); map.remove("y");
List all key–value pairs and explain what happened to "x" and "y".Show answer
Question 3: INTERMEDIATE
charFrequency that takes a String parameter and returns a HashMap<Character, Integer> containing the frequency of each character. For example, charFrequency("hello") should return {h=1, e=1, l=2, o=1}.Show answer
Question 4: APPLIED
String[] votes = {"Alice", "Bob", "Alice", "Charlie", "Bob", "Alice", "Bob", "Bob"}; Write code that uses a HashMap to count votes and then prints the winner (the candidate with the most votes). Handle the possibility of a tie by printing all candidates who share the highest vote count.Show answer
Question 5: CRITICAL THINKING
boolean areAnagrams(String a, String b) that uses HashMap to determine whether two strings are anagrams. Explain why HashMap is a good choice here and discuss the time complexity of your solution.Show answer
SUMMARY
Lesson Summary
Summary
A HashMap is a data structure that stores key–value pairs and provides O(1) average-time access for putting, getting, and removing entries. Internally, it uses a hash function to map each key to a bucket index in an array. When two keys hash to the same index (a collision), Java chains them together in that bucket. You create a HashMap with new HashMap<>(), store entries with put(), retrieve them with get(), and check for keys with containsKey().
The most essential pattern to remember is frequency counting: map.put(item, map.getOrDefault(item, 0) + 1). This one-liner uses getOrDefault() to safely handle both new and existing keys. To iterate over all entries, use entrySet() for access to both keys and values. HashMap doesn't maintain insertion order (use LinkedHashMap for that) and doesn't sort entries (use TreeMap for that). Master the frequency counting pattern and the core methods, and you'll have a powerful tool for solving a wide range of programming problems.