Evens and partitioning, numbers starting with 1, duplicates (three correct ways), first element, count, max, first non-repeated and first repeated character, ascending and descending sort, and contains-duplicate — with the bugs in common answers fixed.
Published September 25, 2026
These are the stream problems asked in live coding at the 2–5 year level. Interviewers look for three things: a correct pipeline, no side effects hidden in lambdas, and awareness of edge cases (empty input, case, whitespace). Several popular answers online mutate a shared HashSet inside filter. It works in a demo, but it's a hidden bug. The versions below avoid it.
Sample data:
List<Integer> nums = List.of(10, 15, 8, 49, 25, 98, 98, 32, 15);
List<Integer> evens = nums.stream().filter(n -> n % 2 == 0).toList(); // [10, 8, 98, 98, 32]
Map<Boolean, List<Integer>> evenOdd = nums.stream()
.collect(Collectors.partitioningBy(n -> n % 2 == 0)); // {false=[15,49,25,15], true=[10,8,98,98,32]}
Key points to cover:
partitioningBy returns both groups in one pass, and always includes both keys.int[], use Arrays.stream(arr).filter(...).toArray() to avoid boxing.Learn it in depth → Collectors
List<Integer> startsWith1 = nums.stream()
.filter(n -> String.valueOf(n).startsWith("1"))
.toList(); // [10, 15, 15]
Key points to cover:
String.valueOf(Math.abs(n)) if "−15 starts with 1" should count.Correct, side-effect-free versions:
// 1) group and count: duplicates listed once, with first-seen order kept
List<Integer> duplicates = nums.stream()
.collect(Collectors.groupingBy(Function.identity(), LinkedHashMap::new, Collectors.counting()))
.entrySet().stream()
.filter(e -> e.getValue() > 1)
.map(Map.Entry::getKey)
.toList(); // [15, 98]
// 2) frequency check: simple, but O(n²)
List<Integer> dups2 = nums.stream().filter(n -> Collections.frequency(nums, n) > 1).distinct().toList();
// removing duplicates instead (the other half of the question)
List<Integer> unique = nums.stream().distinct().toList(); // order preserved
Common trap: Set<Integer> seen = new HashSet<>(); nums.stream().filter(n -> !seen.add(n)). The lambda mutates external state, so it's not safe for parallel streams, and it outputs an element once per extra occurrence (a value appearing three times is reported twice). Use grouping instead.
Optional<Integer> first = nums.stream().findFirst(); // Optional[10]
first.ifPresent(System.out::println);
Key points to cover:
List, list.isEmpty() ? null : list.get(0) is simpler. On Java 21, use list.getFirst(), which throws on an empty list. Use streams when the first element comes after filtering.long total = nums.stream().count(); // 9
long distinctCount = nums.stream().distinct().count(); // 7
Key points to cover:
nums.size() is the right answer. count() makes sense after filter or distinct.int max = nums.stream().max(Comparator.naturalOrder()).orElseThrow(); // 98
int max2 = nums.stream().mapToInt(Integer::intValue).max().orElse(Integer.MIN_VALUE);
Common trap: calling .get() on the Optional without thinking about the empty list. Choose orElseThrow with a clear message, or a documented default.
String input = "Java articles are Awesome";
Optional<Character> firstUnique = input.chars()
.mapToObj(c -> Character.toLowerCase((char) c))
.filter(Character::isLetter) // ignore spaces (clarify with the interviewer)
.collect(Collectors.groupingBy(Function.identity(), LinkedHashMap::new, Collectors.counting()))
.entrySet().stream()
.filter(e -> e.getValue() == 1)
.map(Map.Entry::getKey)
.findFirst(); // Optional[j]
Key points to cover:
LinkedHashMap keeps the first-occurrence order. With a plain HashMap the answer would be arbitrary.indexOf(c) == lastIndexOf(c) one-liner is O(n²). Mention it only as the simple version.Short answer: Be precise about the definition. Usually it means "the first character, scanning left to right, that has already appeared earlier". A loop with a Set is the clearest correct answer. The grouping approach returns the first character (by first appearance) that repeats anywhere, which can differ.
static Optional<Character> firstRepeated(String s) {
Set<Character> seen = new HashSet<>();
for (char c : s.toLowerCase(Locale.ROOT).toCharArray()) {
if (Character.isLetter(c) && !seen.add(c)) return Optional.of(c); // first char seen twice
}
return Optional.empty();
}
// "Java Articles are Awesome" → 'a' (index 3 repeats the 'a' at index 1)
// stream version of "first character (by first appearance) that occurs more than once"
Optional<Character> firstThatRepeats = s.toLowerCase().chars()
.mapToObj(c -> (char) c).filter(Character::isLetter)
.collect(Collectors.groupingBy(Function.identity(), LinkedHashMap::new, Collectors.counting()))
.entrySet().stream().filter(e -> e.getValue() > 1).map(Map.Entry::getKey).findFirst();
Key points to cover:
List<Integer> ascending = nums.stream().sorted().toList(); // [8, 10, 15, 15, 25, 32, 49, 98, 98]
List<Integer> descending = nums.stream().sorted(Comparator.reverseOrder()).toList();
List<Integer> descUnique = nums.stream().distinct().sorted(Comparator.reverseOrder()).toList();
Key points to cover:
Collections.reverseOrder() and Comparator.reverseOrder() are equivalent here. For objects, Comparator.comparing(Employee::salary).reversed().true if any value appears at least twice.static boolean containsDuplicate(int[] nums) {
return Arrays.stream(nums).distinct().count() != nums.length; // simple and side-effect free
}
static boolean containsDuplicateFast(int[] nums) {
Set<Integer> seen = new HashSet<>();
for (int n : nums) if (!seen.add(n)) return true; // short-circuits at the first duplicate
return false;
}
// [1, 2, 3, 1] → true [1, 2, 3, 4] → false
Key points to cover:
distinct().count() version always scans everything.Arrays.sort and then comparing neighbours) uses O(1) extra space, but O(n log n) time, and it modifies the input.Learn it in depth → Group Anagrams
Q: How do you find the second-highest number with streams?
A: nums.stream().distinct().sorted(Comparator.reverseOrder()).skip(1).findFirst(). It returns an Optional, which is empty when there are fewer than two distinct values.
Q: How do you count the occurrences of each element?
A: nums.stream().collect(groupingBy(Function.identity(), counting())). Add a TreeMap::new supplier for sorted keys.
Q: Why avoid stateful lambdas in streams? A: The stream specification requires behavioural parameters to be non-interfering and (for most operations) stateless. Stateful lambdas give wrong or non-deterministic results in parallel streams, and make the pipeline's behaviour depend on evaluation order.
Q: How do you find the most frequent element?
A: Group and count, then take entrySet().stream().max(Map.Entry.comparingByValue()). Decide how ties should be broken, and add a secondary comparator if needed.