Java Stream API: 10 Practical Problems I Practiced
While learning Java Streams, I found that understanding individual methods like filter(), map(), reduce(), and collect() is not enough.
The real understanding comes when you start solving small problems using them.
In this post, I’m sharing some Stream API problems I practiced, along with the approach and code for each one.
Note: Most of these examples work with Java 8. Where I use
.toList(), remember thatStream.toList()was introduced in Java 16 and it return unmodifiable list . In Java 8, usecollect(Collectors.toList()).
1. Find Strings Starting With “A”
Problem
Given a list of names, find names starting with the character A.
List<String> names =
List.of("Anuj", "Amit", "Rahul", "Ankit", "Raj");
List<String> result =
names.stream()
.filter(n -> n.startsWith("A"))
.toList();
System.out.println(result);Output
[Anuj, Amit, Ankit]We can also write:
.filter(n -> n.charAt(0) == 'A')Both approaches work.
However, for this particular requirement:
startsWith("A")is more readable because the requirement itself is “starts with A”.
2. Remove Duplicates and Sort in Descending Order
Problem
Remove duplicate numbers and sort the result in descending order.
List<Integer> numbers =
List.of(10, 20, 10, 30, 20, 40, 50);
List<Integer> result =
numbers.stream()
.distinct()
.sorted(Comparator.reverseOrder())
.toList();
System.out.println(result);Output
[50, 40, 30, 20, 10]Important operations
distinct():
.distinct()removes duplicate elements.
So:
10, 20, 10, 30, 20, 40, 50becomes:
10, 20, 30, 40, 50Then:
.sorted(Comparator.reverseOrder())sorts the elements in descending order.
You might see:
.sorted((a, b) -> b - a)This works for many normal integer values, but subtraction-based comparators can cause integer overflow.
For example, with extreme integer values, b - a may overflow.
A safer approach is:
.sorted(Comparator.reverseOrder())or:
.sorted((a, b) -> Integer.compare(b, a))3. Find the Sum of Numbers Greater Than 25
Problem
Find the sum of all numbers greater than 25.
List<Integer> numbers =
List.of(10, 20, 30, 40, 50);
int result =
numbers.stream()
.filter(n -> n > 25)
.mapToInt(Integer::intValue)
.sum();
System.out.println(result);Output
120Because:
30 + 40 + 50 = 120Another approach using reduce()
We can also write:
Integer result =
numbers.stream()
.filter(n -> n > 25)
.reduce(0, (a, b) -> a + b);Here:
reduce(0, (a, b) -> a + b)starts with 0 and repeatedly combines the values.
For a simple sum, however:
.mapToInt(Integer::intValue)
.sum()is more readable.
4. Find the First Number Greater Than 25
Problem
Find the first number greater than 25.
List<Integer> numbers =
List.of(10, 20, 30, 40, 50);
Optional<Integer> result =
numbers.stream()
.filter(n -> n > 25)
.findFirst();
System.out.println(result.orElse(null));Output
30Why Optional?
findFirst() returns:
Optional<Integer>Because there might be no matching element.
For example:
List<Integer> numbers =
List.of(10, 20, 15);There is no number greater than 25.
Instead of returning null, Java uses Optional to represent the possibility that a value may not exist.
You can also directly write:
Integer result =
numbers.stream()
.filter(n -> n > 25)
.findFirst()
.orElse(null);5. Check Whether Any Number Is Greater Than 18
Problem
Check whether at least one number is greater than 18.
List<Integer> numbers =
List.of(5, 8, 12, 15, 20);
boolean result =
numbers.stream()
.anyMatch(n -> n > 18);
System.out.println(result);Output
trueanyMatch() answers:
Does at least one element satisfy this condition?
In this case:
20 > 18So the answer is true.
6. Check Whether All Numbers Are Positive
Problem
Check whether every number in the list is greater than zero.
List<Integer> numbers =
List.of(10, 20, 30, 40);
boolean result =
numbers.stream()
.allMatch(n -> n > 0);
System.out.println(result);Output
trueallMatch() answers:
Do all elements satisfy this condition?
For example:
List<Integer> numbers =
List.of(10, 20, -5, 40);Then:
.allMatch(n -> n > 0)returns:
falsebecause -5 is not greater than zero.
7. Find the Longest String
Problem
Find the longest name from a list.
List<String> names =
List.of("Anuj", "Amit", "Rahul", "Ankit", "Raj");
Optional<String> result =
names.stream()
.max(Comparator.comparingInt(String::length));
System.out.println(result.orElse(null));Output
RahulHere:
Comparator.comparingInt(String::length)compares the Strings based on their length.
So:
Anuj → 4
Amit → 4
Rahul → 5
Ankit → 5
Raj → 3The maximum length is 5.
8. Find the Second Largest Number
Problem
Find the second largest distinct number.
List<Integer> numbers =
List.of(10, 50, 20, 50, 30, 40);
Optional<Integer> result =
numbers.stream()
.distinct()
.sorted(Comparator.reverseOrder())
.skip(1)
.findFirst();
System.out.println(result.orElse(null));Output
40Let’s understand the pipeline:
Get Anuj Singh’s stories in your inbox
Join Medium for free to get updates from this writer.
Original:
10, 50, 20, 50, 30, 40After distinct():
10, 50, 20, 30, 40After descending sort:
50, 40, 30, 20, 10After:
.skip(1)we skip 50:
40, 30, 20, 10Then:
.findFirst()returns:
409. Find Numbers That Occur Exactly Twice
This is a slightly more interesting problem.
Problem
Given:
List<Integer> numbers =
List.of(10, 50, 10, 50, 30, 40, 10, 30);Find numbers that occur exactly twice.
List<Integer> result =
numbers.stream()
.filter(n -> Collections.frequency(numbers, n) == 2)
.distinct()
.toList();
System.out.println(result);Output
[50, 30]Frequency:
10 → 3
50 → 2
30 → 2
40 → 1Therefore:
50 and 30occur exactly twice.
Why distinct()?
Without:
.distinct()the stream would contain:
50, 50, 30, 30We only want:
50, 30so we use distinct().
10. Find Strings Occurring At Least Twice
We can apply the same idea to Strings.
List<String> names =
List.of("Anuj", "Rahul", "Anuj", "Amit", "Rahul", "Anuj");
List<String> result =
names.stream()
.filter(n -> Collections.frequency(names, n) >= 2)
.distinct()
.toList();
System.out.println(result);Output:
[Anuj, Rahul]The frequencies are:
Anuj → 3
Rahul → 2
Amit → 1So only Anuj and Rahul satisfy:
frequency >= 211. Better Approach: groupingBy() + counting()
Although Collections.frequency() works, a better approach exists for frequency problems.
List<String> names =
List.of("Anuj", "Rahul", "Anuj", "Amit", "Rahul", "Anuj");
List<String> result =
names.stream()
.collect(Collectors.groupingBy(
Function.identity(),
Collectors.counting()
))
.entrySet()
.stream()
.filter(e -> e.getValue() >= 2)
.map(Map.Entry::getKey)
.toList();
System.out.println(result);Output:
[Anuj, Rahul]What does groupingBy() produce?
Conceptually:
Anuj → 3
Rahul → 2
Amit → 1So we can think of it as:
Map<String, Long>Then:
.filter(e -> e.getValue() >= 2)keeps:
Anuj → 3
Rahul → 2And:
.map(Map.Entry::getKey)extracts only the names:
Anuj
RahulFinally:
.toList()stores them in a List<String>.
Important Stream Operations I Practiced
The problems above covered several commonly used Stream operations:
filter()
Used when we want to select elements based on a condition.
.filter(n -> n > 20)map()
Used to transform elements.
.map(n -> n * n)or:
.map(String::length)distinct()
Removes duplicate elements.
.distinct()sorted()
Sorts elements.
.sorted()Descending:
.sorted(Comparator.reverseOrder())reduce()
Combines elements into a single result.
.reduce(0, (a, b) -> a + b)findFirst()
Returns the first matching element as an Optional.
.findFirst()anyMatch()
Checks whether at least one element matches.
.anyMatch(n -> n > 18)allMatch()
Checks whether every element matches.
.allMatch(n -> n > 0)max()
Finds the maximum element according to a comparator.
.max(Comparator.comparingInt(String::length))skip()
Skips a specified number of elements.
.skip(1)collect()
Used to collect Stream results into a collection or another result type.
For example, in Java 8:
.collect(Collectors.toList())In modern Java:
.toList()Final Takeaway
The most important thing I learned from these exercises is that Stream API is not about memorizing methods individually.
It’s about understanding how operations can be combined into a pipeline:
Once the purpose of each operation becomes clear, solving Stream-based interview questions becomes much easier.
💡 Preparing for Java interviews? Follow me for more interview questions and answers on Java, Spring Boot, Microservices, SQL, and backend development — explained in a simple, practical, and interview-focused way. 🚀 Let’s crack interviews and grow together!







