Count Occurrences Using Streams
Java coding interview problem for Java 8 Streams: Count Occurrences Using Streams.
Counting occurrences of elements is one of the most common Java Collections and Stream API interview problems.
Examples:
- Count how many times a number appears.
- Count character frequency.
- Count word occurrences.
- Count employees by department.
This problem introduces:
- Stream API
filter()count()Collectors.groupingBy()Collectors.counting()- Frequency analysis
What is Counting Occurrences?
Occurrence counting means finding how many times an element appears in a collection.
Example:
Input:
[10,20,10,30,20,10]
Count:
10 → 3 times
20 → 2 times
30 → 1 time
Understanding Frequency and Occurrence Counting
Occurrence:
Number of times a particular element appears.
Frequency:
A mapping between elements and their occurrence count.
Example:
Input:
apple
Character frequency:
a → 1
p → 2
l → 1
e → 1
Difference Between Count and Frequency Map
Count
Returns:
Single number
Example:
How many times does:
Java
appear?
Output:
3
Frequency Map
Returns:
Element → Count
Example:
Java → 3
Spring → 2
AWS → 1
Why Occurrence Problems Are Important?
Occurrence counting is the foundation of many algorithms.
It helps with:
- Duplicate detection
- Frequency analysis
- Data aggregation
- Searching patterns
- Analytics
Real-World Applications
Log Analysis
Count:
Error messages
Warning messages
Request types
Banking Systems
Count:
Transaction types
Failed payments
Successful payments
Search Engines
Analyze:
Keyword frequency
E-Commerce
Count:
Product views
Customer purchases
Problem Statement
Given a list of elements, count how many times a specific element occurs using Java Streams.
Example 1
Input:
[10,20,10,30,10]
Find:
10
Output:
10 occurs 3 times
Example 2
Input:
["Java","Spring","Java","AWS"]
Find:
Java
Output:
Java occurs 2 times
Java Stream API Overview
Streams provide a functional way to process collections.
Stream flow:
Collection
↓
Stream
↓
Operations
↓
Result
Example:
list.stream()
creates a stream pipeline.
Stream Pipeline Concept
Example:
numbers.stream()
.filter()
.count();
Flow:
List
↓
stream()
↓
Filter Matching Elements
↓
Count Results
Approach 1 — Traditional Loop Approach
Before Streams, counting was done using loops.
Algorithm
- Create counter.
- Traverse collection.
- Compare elements.
- Increment count.
Java Program
import java.util.*;
public class CountOccurrences {
public static int count(
List<Integer> numbers,
int target) {
int count = 0;
for(Integer number : numbers) {
if(number == target) {
count++;
}
}
return count;
}
public static void main(String[] args) {
List<Integer> numbers =
Arrays.asList(
10,
20,
10,
30,
10
);
System.out.println(
count(numbers,10)
);
}
}
Output
3
Dry Run
Input:
[10,20,10,30,10]
Target:
10
Initial:
count = 0
Read:
10
Match.
count = 1
Read:
20
No match.
Read:
10
Match.
count = 2
Read:
30
No match.
Read:
10
Match.
count = 3
Final:
3
Complexity Analysis — Loop Approach
Let:
n = number of elements
Traversal:
O(n)
Space:
O(1)
Approach 2 — Using Stream filter() and count()
Java Streams provide:
filter()
and:
count()
for occurrence counting.
Syntax
stream()
.filter(condition)
.count();
Java Program
import java.util.*;
public class CountUsingStreams {
public static long count(
List<Integer> numbers,
int target) {
return numbers.stream()
.filter(
number ->
number == target
)
.count();
}
public static void main(String[] args) {
List<Integer> numbers =
Arrays.asList(
10,
20,
10,
30,
10
);
System.out.println(
count(numbers,10)
);
}
}
Output
3
Step-by-Step Stream Explanation
Input:
[10,20,10,30,10]
Stream:
10
20
10
30
10
Filter:
number == 10
Evaluation:
10 → true
20 → false
10 → true
30 → false
10 → true
Remaining:
10
10
10
Count:
3
Stream Pipeline Diagram
List<Integer>
↓
stream()
↓
filter()
↓
Matching Elements
↓
count()
↓
Long Result
Counting Character Occurrences
Example:
Input:
"programming"
Find:
g
Expected:
g occurs 2 times
Java Program
public static long countCharacter(
String text,
char target) {
return text.chars()
.filter(
ch ->
ch == target
)
.count();
}
Explanation
String:
programming
Characters:
p r o g r a m m i n g
Filter:
g == target
Matches:
g
g
Result:
2
Counting Word Occurrences
Example:
Input:
"Java Spring Java AWS Java"
Find:
Java
Java Program
String text =
"Java Spring Java AWS Java";
long count =
Arrays.stream(
text.split(" ")
)
.filter(
word ->
word.equals("Java")
)
.count();
Output:
3
Approach 3 — Using Collectors.groupingBy()
Instead of counting one element, we often need all frequencies.
Example:
Input:
[Java,Spring,Java,AWS,Spring]
Expected:
Java → 2
Spring → 2
AWS → 1
Java Program
import java.util.*;
import java.util.stream.Collectors;
Map<String,Long> frequency =
words.stream()
.collect(
Collectors.groupingBy(
word -> word,
Collectors.counting()
)
);
Output
{
Java=2,
Spring=2,
AWS=1
}
Step-by-Step Explanation
Input:
Java
Spring
Java
AWS
Spring
Grouping:
Java group
Spring group
AWS group
Counting:
Java → 2
Spring → 2
AWS → 1
Understanding Collectors.counting()
Collector:
Collectors.counting()
counts elements inside each group.
Example:
Group:
Java
Java
Count:
2
Handling Case Sensitivity
Input:
Java
java
JAVA
Default:
Different values:
Java → 1
java → 1
JAVA → 1
Case-insensitive:
Convert:
toLowerCase()
Example:
words.stream()
.map(
String::toLowerCase
)
.collect(
Collectors.groupingBy(
word -> word,
Collectors.counting()
)
);
Handling Null Values
Input:
[Java,null,AWS]
Filter:
words.stream()
.filter(
Objects::nonNull
)
.count();
Time and Space Complexity
filter() + count()
Time:
O(n)
Space:
O(1)
groupingBy() Frequency Map
Time:
O(n)
Space:
O(k)
where:
k = unique elements
Advantages
- Clean functional approach.
- Easy frequency analysis.
- Less boilerplate.
- Supports complex grouping.
Drawbacks
- Requires Stream knowledge.
- Frequency maps require additional memory.
- Debugging can be harder.
Deep Dive Into Collectors.counting()
Collectors.counting() is a downstream collector used with grouping operations.
It counts:
Number of elements inside each group
Syntax
Collectors.counting()
Example:
Map<String,Long> result =
words.stream()
.collect(
Collectors.groupingBy(
word -> word,
Collectors.counting()
)
);
Input:
Java
Spring
Java
Processing:
Grouping:
Java → [Java,Java]
Spring → [Spring]
Counting:
Java → 2
Spring → 1
Counting Duplicate Elements
A common interview question:
Find duplicate elements in a list.
Example:
Input:
[10,20,10,30,20,40]
Frequency:
10 → 2
20 → 2
30 → 1
40 → 1
Duplicates:
10
20
Java Program
List<Integer> duplicates =
numbers.stream()
.collect(
Collectors.groupingBy(
number -> number,
Collectors.counting()
)
)
.entrySet()
.stream()
.filter(
entry ->
entry.getValue() > 1
)
.map(
Map.Entry::getKey
)
.toList();
Dry Run
Input:
[10,20,10,30,20]
Grouping:
10 → [10,10]
20 → [20,20]
30 → [30]
Counting:
10 → 2
20 → 2
30 → 1
Filter:
count > 1
Result:
[10,20]
Finding Most Frequent Element
Problem:
Find the element that appears maximum times.
Example:
Input:
[Java,AWS,Java,Spring,Java]
Frequency:
Java → 3
AWS → 1
Spring → 1
Result:
Java
Java Program
String mostFrequent =
words.stream()
.collect(
Collectors.groupingBy(
word -> word,
Collectors.counting()
)
)
.entrySet()
.stream()
.max(
Map.Entry.comparingByValue()
)
.map(
Map.Entry::getKey
)
.orElse(null);
Explanation
Step 1:
Create frequency map.
Java → 3
AWS → 1
Spring → 1
Step 2:
Find maximum value.
Java → 3
Step 3:
Return key.
Java
Finding First Repeated Element
Problem:
Find the first element that appears more than once.
Example:
Input:
[5,3,8,3,5]
Output:
3
because:
3 appears first as duplicate
Java Program
Integer firstRepeated =
numbers.stream()
.filter(
number ->
Collections.frequency(
numbers,
number
) > 1
)
.findFirst()
.orElse(null);
Note:
Collections.frequency() scans the list repeatedly.
For large data, use:
HashMap frequency counting
Better Stream Approach
Map<Integer,Long> frequency =
numbers.stream()
.collect(
Collectors.groupingBy(
number -> number,
Collectors.counting()
)
);
Integer result =
numbers.stream()
.filter(
number ->
frequency.get(number) > 1
)
.findFirst()
.orElse(null);
Counting Object Occurrences
Streams can count custom objects.
Example:
Order:
orderId
status
Requirement:
Count orders by status.
Input:
ORDER_CREATED
ORDER_COMPLETED
ORDER_CREATED
Expected:
ORDER_CREATED → 2
ORDER_COMPLETED → 1
Java Program
Map<String,Long> statusCount =
orders.stream()
.collect(
Collectors.groupingBy(
Order::getStatus,
Collectors.counting()
)
);
Counting Employees by Department
Common enterprise interview question.
Employee:
John IT
Alice HR
Bob IT
David Finance
Expected:
IT → 2
HR → 1
Finance → 1
Java Program
Map<String,Long> employeeCount =
employees.stream()
.collect(
Collectors.groupingBy(
Employee::getDepartment,
Collectors.counting()
)
);
Counting Transactions by Status
Example:
Transactions:
SUCCESS
FAILED
SUCCESS
PENDING
Result:
SUCCESS → 2
FAILED → 1
PENDING → 1
Code:
Map<String,Long> result =
transactions.stream()
.collect(
Collectors.groupingBy(
Transaction::getStatus,
Collectors.counting()
)
);
count() vs counting()
Both count elements, but they are used differently.
Stream count()
Used directly on a Stream.
Example:
long count =
numbers.stream()
.filter(
n -> n > 10
)
.count();
Returns:
Single count value
Example:
Numbers greater than 10 = 5
Collectors.counting()
Used inside collectors.
Example:
Collectors.groupingBy(
Employee::getDepartment,
Collectors.counting()
)
Returns:
Count per group
Comparison
| Feature | count() | counting() |
|---|---|---|
| Usage | Terminal operation | Collector |
| Result | One count | Group counts |
| Works with | Stream | Collectors |
| Example | Count all values | Count by category |
Primitive Stream Counting
Java provides:
IntStream
LongStream
DoubleStream
Example:
long count =
IntStream
.of(1,2,3,4,5)
.filter(
n -> n % 2 == 0
)
.count();
Output:
2
Stream vs Loop Comparison
| Feature | Loop | Streams |
|---|---|---|
| Code | More | Compact |
| Readability | Simple | Declarative |
| Grouping | Manual Map handling | Collectors |
| Parallel support | Manual | Built-in |
| Functional style | No | Yes |
HashMap Internal Working
Frequency counting usually uses:
HashMap
When adding:
map.put(value,count)
Java performs:
Element
↓
hashCode()
↓
Bucket
↓
Store Count
Example:
Java → 3
Internally:
Key:
Java
Value:
3
Parallel Stream Considerations
For large datasets:
parallelStream()
can process groups in parallel.
Example:
Map<String,Long> result =
words.parallelStream()
.collect(
Collectors.groupingByConcurrent(
word -> word,
Collectors.counting()
)
);
Benefits:
- Parallel execution
- Better large-scale processing
Consider:
- Dataset size
- Thread overhead
- Ordering requirements
Common Interview Mistakes
Mistake 1
Using:
count()
for frequency maps.
Wrong:
Need each element count
Use:
groupingBy() + counting()
Mistake 2
Ignoring case sensitivity.
Example:
Java
java
Different values.
Solution:
.map(
String::toLowerCase
)
Mistake 3
Using repeated frequency scans.
Example:
Collections.frequency()
inside loops.
Problem:
O(n²)
Mistake 4
Ignoring null values.
Use:
.filter(
Objects::nonNull
)
Edge Cases
| Case | Handling |
|---|---|
| Empty list | Return empty map |
| Single element | Count = 1 |
| All duplicates | One frequency entry |
| Null values | Filter or handle |
| Large data | Consider concurrent collectors |
Interview Follow-up Questions
Q1. Difference between count() and counting()?
Q2. Find duplicate elements using Streams.
Q3. Find most frequent character.
Q4. Count employees by department.
Q5. How does groupingBy() work internally?
Q6. How to handle duplicate objects?
Q7. How to optimize frequency counting?
Related Java Collection Problems
- Character Frequency Using Streams
- Count Word Frequency Using HashMap
- Find Duplicate Elements Using Streams
- Group Employees by Department
- Remove Duplicates Using Streams
- Convert List to Map Using Streams
Key Takeaways
Occurrence counting patterns:
Single Element Count
↓
filter()
↓
count()
Frequency Map:
Elements
↓
groupingBy()
↓
counting()
↓
Element → Count
Duplicate Detection:
Frequency
↓
count > 1
↓
Duplicates
Most Frequent:
Frequency Map
↓
max()
↓
Highest Count Element
Complexity:
Simple count:
O(n)
Frequency map:
O(n)
Space:
O(k)
where:
k = unique elements
Frequently Asked Interview Questions
Q1. Why use groupingBy() with counting()?
Because groupingBy creates groups and counting calculates the size of each group.
Q2. Difference between count() and counting()?
count() counts stream elements directly.
counting() counts elements inside a collector.
Q3. How to find duplicate elements?
Create frequency map and filter:
count > 1
Q4. How to find the most frequent element?
Use:
groupingBy()
+
counting()
+
max()
Interview Tip
When asked:
"Count occurrences using Java Streams."
Explain:
- For one value use
filter().count(). - For all frequencies use
groupingBy().counting(). - For duplicates filter frequency greater than one.
- Handle case sensitivity and null values.
- Discuss HashMap-based complexity.
For senior Java interviews, discuss:
- Collector design.
- Frequency map patterns.
- HashMap internals.
- Parallel collectors.
- Performance optimization.
This demonstrates strong understanding of Java Streams, Collections, and data aggregation patterns.