In this tutorial, I will demonstrate how to count the frequency of elements in a List using HashMap in Java. This is a common Java coding interview question that helps you understand how to use maps to count duplicate values efficiently.
The frequency of an element represents the number of times it appears in a collection. For example, if the number 10 appears three times in a list, its frequency is 3.
Java's HashMap is well-suited for this problem because it stores data as key-value pairs. You can store each distinct element as a key and its occurrence count as the corresponding value.
In this tutorial, you will learn how to count element frequencies using HashMap, getOrDefault(), and merge(). I will also explain the algorithm with a dry run, show how to count string occurrences, and discuss time complexity and important edge cases.
1. Problem Statement
Write a Java program to count the frequency of every element in a List using HashMap.
For each distinct element, display how many times it appears in the list.
Example 1: Integer List
Input: [10, 20, 10, 30, 20, 10, 40, 30] Output: 10 = 3 20 = 2 30 = 2 40 = 1
Explanation:
- The number 10 appears three times.
- The number 20 appears twice.
- The number 30 appears twice.
- The number 40 appears once.
Example 2: String List
Input: [Java, Python, Java, Spring, Python, Java] Output: Java = 3 Python = 2 Spring = 1
The same technique works for integers, strings, and other types of objects that provide appropriate equality and hash-code behavior.
2. Method 1: Count Element Frequency Using HashMap and getOrDefault()
The most straightforward approach is to use HashMap with the getOrDefault() method.
A HashMap stores each distinct element as a key and its frequency as the value.
When the program encounters an element, it retrieves the current count, adds one, and updates the map.
Java Program Using HashMap
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class ElementFrequencyUsingHashMap {
/**
* Counts how many times each integer appears.
*
* @param numbers list of integers
* @return map containing each number and its frequency
*/
public static Map<Integer, Integer> countFrequency(
List<Integer> numbers) {
Map<Integer, Integer> frequencyMap =
new HashMap<>();
for (Integer number : numbers) {
int count = frequencyMap.getOrDefault(
number, 0);
frequencyMap.put(number, count + 1);
}
return frequencyMap;
}
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(
10, 20, 10, 30, 20, 10, 40, 30
);
Map<Integer, Integer> frequencyMap =
countFrequency(numbers);
System.out.println("Original List: " + numbers);
System.out.println("Element Frequencies:");
// Sort keys only for predictable display
Map<Integer, Integer> sorted =
new TreeMap<>(frequencyMap);
for (Map.Entry<Integer, Integer> entry
: sorted.entrySet()) {
System.out.println(
entry.getKey() + " = " + entry.getValue());
}
}
}
Output
Original List: [10, 20, 10, 30, 20, 10, 40, 30] Element Frequencies: 10 = 3 20 = 2 30 = 2 40 = 1
Note: HashMap does not guarantee iteration order. The example uses a TreeMap only when displaying the results so the output appears in ascending key order. The frequency-counting algorithm itself uses HashMap.
3. Step-by-Step Explanation
Step 1: Create an Empty HashMap
Map<Integer, Integer> frequencyMap =
new HashMap<>();
The HashMap stores each integer as a key and its occurrence count as the value.
For example, a mapping of 10 = 3 means the number 10 appears three times.
Step 2: Iterate Through the List
for (Integer number : numbers) {
The enhanced for loop processes every element in the List.
Step 3: Retrieve the Current Frequency
int count = frequencyMap.getOrDefault(
number, 0);
The getOrDefault() method returns the value associated with the specified key.
If the key is not present, it returns the provided default value, which is zero in this example.
For instance:
- When 10 appears for the first time, its existing count is 0.
- When 10 appears again, its existing count is 1.
- When 10 appears for the third time, its existing count is 2.
Step 4: Update the Frequency
frequencyMap.put(number, count + 1);
The put() method stores the updated count in the HashMap.
If the key already exists, its value is replaced with the new count.
The complete frequency-counting statement can also be written in one line:
frequencyMap.put(
number,
frequencyMap.getOrDefault(number, 0) + 1
);
Step 5: Display the Frequency Map
Each entry contains one distinct element and its count.
You can access the entries using entrySet():
for (Map.Entry<Integer, Integer> entry
: frequencyMap.entrySet()) {
System.out.println(
entry.getKey() + " = " + entry.getValue());
}
Because HashMap does not guarantee iteration order, the entries may be displayed in a different order.
4. Dry Run: Counting Element Frequencies
Consider this input:
[10, 20, 10, 30, 20, 10]
Initially, the HashMap is empty.
The algorithm processes each element and updates its frequency.
| Step | Current Element | Previous Count | Updated Frequency Map |
|---|---|---|---|
| 1 | 10 | 0 | {10=1} |
| 2 | 20 | 0 | {10=1, 20=1} |
| 3 | 10 | 1 | {10=2, 20=1} |
| 4 | 30 | 0 | {10=2, 20=1, 30=1} |
| 5 | 20 | 1 | {10=2, 20=2, 30=1} |
| 6 | 10 | 2 | {10=3, 20=2, 30=1} |
The map contents above are shown in key order for readability; the actual HashMap iteration order is unspecified.
Final result:
10 = 3 20 = 2 30 = 1
5. Method 2: Count Frequency Using HashMap.merge()
Java 8 introduced the merge() method in the Map interface.
It provides a concise way to insert a value when a key is absent or update the existing value when the key is already present.
For frequency counting, you can use merge() with Integer::sum.
Java Program Using merge()
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class FrequencyUsingMerge {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(
10, 20, 10, 30, 20, 10, 40, 30
);
Map<Integer, Integer> frequencyMap =
new HashMap<>();
// Count occurrences using merge()
for (Integer number : numbers) {
frequencyMap.merge(number, 1, Integer::sum);
}
// Display entries in ascending key order
Map<Integer, Integer> sorted =
new TreeMap<>(frequencyMap);
sorted.forEach((number, count) ->
System.out.println(number + " = " + count));
}
}
Output
10 = 3 20 = 2 30 = 2 40 = 1
How merge() Works
Consider this statement:
frequencyMap.merge(number, 1, Integer::sum);
It performs two possible operations:
- If the key is absent, insert it with a frequency of 1.
- If the key already has a non-null count, add 1 to that count.
The Integer::sum method reference adds the previous count and the supplied value.
For example, when the number 10 appears three times, its frequency changes from 1 to 2 and then to 3.
This approach reduces the counting logic to a single statement inside the loop.
6. Method 3: Count String Frequencies Using HashMap
The same algorithm works with strings.
Instead of storing an Integer as the key, use a String as the key.
Java Program to Count Word Occurrences
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class StringFrequencyUsingHashMap {
public static void main(String[] args) {
List<String> languages = Arrays.asList(
"Java",
"Python",
"Java",
"Spring",
"Python",
"Java"
);
Map<String, Integer> frequencyMap =
new HashMap<>();
// Count occurrences of each language
for (String language : languages) {
frequencyMap.put(
language,
frequencyMap.getOrDefault(language, 0) + 1
);
}
Map<String, Integer> sorted =
new TreeMap<>(frequencyMap);
sorted.forEach((language, count) ->
System.out.println(language + " = " + count));
}
}
Output
Java = 3 Python = 2 Spring = 1
This example counts the number of occurrences of each programming language.
String comparisons are case-sensitive by default, so "Java" and "java" would be counted as separate keys.
7. Method 4: Count Frequencies Using Java Streams
Although HashMap is an excellent choice for frequency counting, the Stream API provides another concise solution.
You can use Collectors.groupingBy() together with Collectors.counting().
Java Program Using Streams
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
public class FrequencyUsingStreams {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(
10, 20, 10, 30, 20, 10, 40, 30
);
Map<Integer, Long> frequencyMap =
numbers.stream()
.collect(Collectors.groupingBy(
number -> number,
Collectors.counting()
));
Map<Integer, Long> sorted =
new TreeMap<>(frequencyMap);
sorted.forEach((number, count) ->
System.out.println(number + " = " + count));
}
}
Output
10 = 3 20 = 2 30 = 2 40 = 1
The groupingBy() collector groups identical elements, while counting() calculates how many elements belong to each group.
Note: This Stream solution uses a Map with Long frequency values because Collectors.counting() returns Long counts.
The main focus of this tutorial remains the HashMap approach, which demonstrates the frequency-counting algorithm directly.
8. Time and Space Complexity
The HashMap approach processes every list element once.
For each element, it performs a lookup and an update.
| Approach | Expected Counting Time | Auxiliary Space |
|---|---|---|
| HashMap with getOrDefault() | O(n) | O(k) |
| HashMap with merge() | O(n) | O(k) |
| Streams with groupingBy() | O(n) expected | O(k) |
Here:
nrepresents the total number of elements in the list.krepresents the number of distinct elements.
Time Complexity: O(n) Expected
Each element is processed once, and HashMap operations generally take constant time on average.
Therefore, building the frequency map takes O(n) expected time.
Hash collisions and expensive key comparisons can affect performance, so constant-time operations are not guaranteed in every situation.
The examples additionally create a TreeMap to display keys in sorted order. That optional display step takes O(k log k) time, making the overall complexity of the complete demonstration O(n + k log k).
Space Complexity: O(k)
The HashMap stores one entry for every distinct element.
If every element is unique, k = n, and the space complexity becomes O(n).
The optional TreeMap used for sorted output also requires O(k) additional storage.
9. Handling Important Edge Cases
Case 1: Empty List
Input:
[]
Output:
{}
The algorithm returns an empty HashMap when the input list contains no elements.
Case 2: All Elements Are Unique
Input: [10, 20, 30, 40] Frequencies: 10 = 1 20 = 1 30 = 1 40 = 1
Each element has a frequency of one.
Case 3: All Elements Are Identical
Input: [5, 5, 5, 5, 5] Frequencies: 5 = 5
The HashMap stores only one entry because all elements have the same value.
Case 4: Negative Numbers and Zero
Input: [-10, 0, -10, 5, 0] Frequencies: -10 = 2 0 = 2 5 = 1
HashMap works with negative integers and zero without additional logic.
Case 5: List Contains Null Elements
Input: [10, null, 20, null, 10] Frequencies: 10 = 2 20 = 1 null = 2
HashMap supports a null key, so the getOrDefault() and merge() approaches can count null elements.
However, the TreeMap display step shown in the integer examples uses natural ordering and does not support null keys. To display frequencies containing null keys, iterate directly over the HashMap entries or use a null-aware Comparator.
Case 6: List Contains String Values with Different Cases
Input: [Java, java, JAVA, Java] Frequencies: JAVA = 1 Java = 2 java = 1
Strings are case-sensitive by default.
If you want case-insensitive counting, normalize the strings before inserting them into the HashMap.
10. Common Mistakes to Avoid
Mistake 1: Forgetting the Default Frequency
If an element appears for the first time, it does not yet exist in the HashMap.
Using get() without checking for a missing key may return null and cause a NullPointerException when unboxed.
Use getOrDefault(element, 0) to handle new elements correctly.
Mistake 2: Assuming HashMap Preserves Insertion Order
HashMap does not guarantee the order in which entries are returned.
If you need elements in their original encounter order, consider LinkedHashMap instead.
If you need keys in sorted order, use TreeMap or sort the entries before displaying them.
Mistake 3: Using Nested Loops Unnecessarily
You can count element frequencies using nested loops, but this usually requires O(n²) time.
HashMap reduces the expected counting time to O(n), making it more suitable for large lists.
Mistake 4: Using Custom Objects Without Correct equals() and hashCode()
If the list contains custom objects, HashMap uses their equals() and hashCode() implementations to identify matching keys.
Without correctly implemented equality and hash-code methods, logically identical objects may be counted as different elements.
Mistake 5: Modifying Frequency Counts Incorrectly
Always increment the current count by one when processing each occurrence.
Do not replace the count with one every time, or the program will lose the accumulated frequency.
11. Frequently Asked Questions
Q1. How do I count the frequency of elements in a List using HashMap?
Iterate through the list and update the count of each element using getOrDefault() or merge().
Q2. What is the easiest way to count occurrences in Java?
One of the simplest approaches is:
frequencyMap.put(
number,
frequencyMap.getOrDefault(number, 0) + 1
);
Q3. Can I use HashMap to count duplicate strings?
Yes. Use HashMap<String, Integer> to store each distinct string and its number of occurrences.
Q4. What is the time complexity of frequency counting with HashMap?
The expected time complexity is O(n) because the algorithm processes each list element once and HashMap operations are typically constant time.
Q5. What is the difference between getOrDefault() and merge()?
The getOrDefault() method retrieves an existing value or supplies a default when the key is absent.
The merge() method can insert a new value or combine it with the current value in a single operation.
Q6. Does HashMap preserve the order of elements?
No. HashMap does not guarantee insertion order. Use LinkedHashMap if order preservation is required.
Q7. Can Java Streams count element frequencies?
Yes. Use Collectors.groupingBy() together with Collectors.counting().
Q8. Does frequency counting modify the original List?
No. The HashMap approaches in this tutorial create a separate map and leave the original list unchanged.
12. Conclusion
In this tutorial, you learned how to count the frequency of elements in a List using HashMap in Java.
- HashMap with getOrDefault(): A straightforward approach that retrieves and increments the frequency of each element.
- HashMap with merge(): A concise way to update frequency counts using a single statement.
- HashMap with String keys: Counts occurrences of words and other string values.
- Java Streams: Uses groupingBy() and counting() to calculate frequencies declaratively.
For Java coding interviews, I recommend learning the getOrDefault() approach first. It clearly demonstrates how HashMap stores keys and values and how frequency counts are updated.
Once you understand the basic algorithm, practice the merge() method. It provides a concise solution and is useful in everyday Java programming.
This frequency-counting pattern also appears in many other interview problems, including finding duplicate elements, identifying the most frequent value, counting words, and checking whether two strings are anagrams.
13. Official Java Documentation
For additional information about the Java APIs used in this tutorial, refer to the official Oracle documentation:
- Java HashMap Class — Documentation for hash-based key-value storage.
- Java Map Interface — Includes
put(),getOrDefault(),merge(), andentrySet(). - Java LinkedHashMap Class — Documentation for maps with predictable encounter order.
- Java TreeMap Class — Documentation for maps with sorted keys.
- Java Collectors Class — Includes
groupingBy()andcounting().
Continue Learning with Java Guides
Want to take your programming skills to the next level? Explore my practical Udemy courses on Java, Spring Boot, Microservices, Full-Stack Development, Docker, and Generative AI. You can also follow my structured learning roadmaps to become a professional developer.
By Ramesh Fadatare - Udemy Instructor Partner
Comments
Post a Comment
Leave Comment