Real Stream Interview Problems
From APIs to problem solving — duplicates, frequencies, first non-repeating element, Nth highest, longest string, per-department analytics and anagrams.
#Introduction
From here on we stop learning APIs and start problem solving — exactly how 5–8 year Java interviews are conducted. The interviewer doesn't ask "What is map()?" Instead they ask:
- "Given this employee list, find the second highest salary."
- "Group employees by department and return the highest-paid employee."
- "Find duplicate characters in a string."
The goal of this chapter is to solve these problems while understanding why a particular Stream solution is the right choice.
#The Problem-Solving Framework
Before writing any code, ask yourself:
- Do I need to filter?
- Do I need to transform?
- Do I need to group?
- Do I need to sort?
- Do I need a single value?
- Do I need a collection?
If you answer these mentally first, the Stream pipeline almost writes itself.
#Number Problems
Problem 1 — Find Duplicate Numbers
List<Integer> list = Arrays.asList(2, 3, 5, 2, 6, 3, 8, 5);Solution (interview favourite):
Set<Integer> seen = new HashSet<>();
list.stream()
.filter(n -> !seen.add(n))
.forEach(System.out::println);2
3
5Why does this work? Remember what Set.add() returns:
seen.add(2); // true (first time)
seen.add(2); // false (already exists)Therefore !seen.add(n) means "keep only duplicates."
Follow-up — why not use distinct()? Because distinct() returns unique elements. We need the opposite.
Problem 2 — Remove Duplicate Numbers
list.stream()
.distinct()
.forEach(System.out::println);Simple.
Problem 3 — Frequency of Numbers
Map<Integer, Long> frequency = list.stream()
.collect(Collectors.groupingBy(
Function.identity(),
Collectors.counting()
));{2=2, 3=2, 5=2, 6=1, 8=1}Why Function.identity()? Instead of n -> n, you can write Function.identity().
Problem 4 — First Non-Repeating Number
Input 2, 3, 2, 5, 6, 5, 7 → expected 3.
Integer result = list.stream()
.collect(Collectors.groupingBy(
Function.identity(),
LinkedHashMap::new,
Collectors.counting()
))
.entrySet()
.stream()
.filter(e -> e.getValue() == 1)
.map(Map.Entry::getKey)
.findFirst()
.orElse(null);Why LinkedHashMap? Very important. A normal HashMap does not preserve insertion order. We need 2, 3, 5, 6, 7 to stay in encounter order so that findFirst() really returns the first non-repeating number.
Problem 8 — Second Highest Number
int second = list.stream()
.distinct()
.sorted(Comparator.reverseOrder())
.skip(1)
.findFirst()
.orElseThrow();Problem 9 — Nth Highest Number
Suppose the 4th highest:
int n = 4;
int result = list.stream()
.distinct()
.sorted(Comparator.reverseOrder())
.skip(n - 1)
.findFirst()
.orElseThrow();Very elegant.
#String Problems
Problem 5 — Character Frequency
Map<Character, Long> result = "programming"
.chars()
.mapToObj(c -> (char) c)
.collect(Collectors.groupingBy(
Function.identity(),
Collectors.counting()
));{p=1, r=2, o=1, g=2, a=1, m=2, i=1, n=1}(The order of a HashMap isn't guaranteed — use LinkedHashMap::new as the map factory if you need encounter order.)
Why chars()? A String is not a collection. chars() converts it into an IntStream, then mapToObj(c -> (char) c) creates a Stream<Character>.
Problem 6 — Duplicate Characters
"programming"
.chars()
.mapToObj(c -> (char) c)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.filter(e -> e.getValue() > 1)
.forEach(System.out::println);r=2
g=2
m=2Problem 7 — First Non-Repeating Character
The most asked Stream interview question. Input programming → expected p.
Character ch = "programming"
.chars()
.mapToObj(c -> (char) c)
.collect(Collectors.groupingBy(
Function.identity(),
LinkedHashMap::new,
Collectors.counting()
))
.entrySet()
.stream()
.filter(e -> e.getValue() == 1)
.map(Map.Entry::getKey)
.findFirst()
.orElse(null);Problem 10 — Longest String
List<String> names = Arrays.asList("John", "Alexander", "Bob");
String longest = names.stream()
.max(Comparator.comparingInt(String::length))
.orElse("");Notice: no sorting. Much faster.
Problem 15 — Group Anagrams
Input eat, tea, tan, ate, nat, bat:
Map<String, List<String>> result = words.stream()
.collect(Collectors.groupingBy(word -> {
char[] chars = word.toCharArray();
Arrays.sort(chars);
return new String(chars);
}));#Employee Problems
Problem 11 — Highest Salary Employee
Employee highest = employees.stream()
.max(Comparator.comparing(Employee::getSalary))
.orElseThrow();Problem 12 — Highest Salary in Each Department
Map<String, Optional<Employee>> result = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.maxBy(Comparator.comparing(Employee::getSalary))
));Classic interview problem.
Problem 13 — Count Employees Per Department
Map<String, Long> result = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.counting()
));Problem 14 — Average Salary Per Department
Map<String, Double> result = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.averagingDouble(Employee::getSalary)
));#Quick-Fire Interview Round
Q1Difference between max() and sorted().findFirst()?
max() is O(n); sorted() is O(n log n). Prefer max().
Q2Why use LinkedHashMap for the first non-repeating character?
Because it preserves insertion order.
Q3Why Function.identity()?
It's equivalent to x -> x.
Q4How do you find duplicates?
filter(n -> !set.add(n)), or group with counting() and keep entries with count > 1.
Q5How do you find the second highest salary?
distinct() → sorted(desc) → skip(1) → findFirst().
#Homework — Top 20 Interview Problems
Using Streams, solve:
- First repeating character.
- Last repeating character.
- Last non-repeating character.
- Most frequent character.
- Least frequent character.
- Reverse each word in a sentence.
- Sort words by length.
- Top 3 longest words.
- Count vowels.
- Count consonants.
- Employees older than 30 grouped by department.
- Department with the highest average salary.
- Youngest employee in each department.
- Employee names in uppercase grouped by department.
- Remove duplicate words from a sentence.
- Most expensive product.
- Top 5 salaries.
- Second youngest employee.
- Third highest unique salary.
- Employees whose names contain only unique characters.
#Pattern Recognition
Knowing Stream methods is one thing. Being able to look at a problem and immediately think "this is a groupingBy + mapping + maxBy problem" is what distinguishes senior Java developers from developers who have memorized the API. That intuition is the skill that consistently helps in interviews.
#Chapter Summary
- The six-question problem-solving framework
- Duplicates with
!seen.add(n)(and its parallel-safety caveat) - Frequency maps with
groupingBy(identity(), counting()) - First non-repeating element with
LinkedHashMap - Nth highest with
distinct → sorted(desc) → skip(n-1) max()oversorted().findFirst()- Group anagrams by sorted key