Skip to content

Java 8 Streams Interview Study Guide

List<Integer> nums = Arrays.asList(1,2,3,4,5,6,7,8);
List<Integer> even =
nums.stream()
.filter(n -> n % 2 == 0)
.toList();

Output:

[2,4,6,8]
nums.stream()
.filter(n -> n % 2 != 0)
.toList();
nums.stream()
.map(n -> n * n)
.toList();
names.stream()
.map(String::toUpperCase)
.toList();
long count = nums.stream().count();
int max = nums.stream().max(Integer::compareTo).get();
int min = nums.stream().min(Integer::compareTo).get();
int sum = nums.stream().mapToInt(Integer::intValue).sum();
Set<Integer> set = new HashSet<>();
List<Integer> duplicates =
nums.stream()
.filter(n -> !set.add(n))
.toList();
nums.stream().distinct().toList();
nums.stream().findFirst().get();
nums.parallelStream().findAny().get();
Method Behavior
findFirst() Preserves encounter order
findAny() Optimized for parallel streams
nums.stream().sorted().toList();
nums.stream()
.sorted(Comparator.reverseOrder())
.toList();
nums.stream()
.sorted(Comparator.reverseOrder())
.limit(3)
.toList();
Integer secondHighest =
nums.stream()
.distinct()
.sorted(Comparator.reverseOrder())
.skip(1)
.findFirst()
.get();
Map<Integer, Long> frequency =
nums.stream()
.collect(Collectors.groupingBy(
Function.identity(),
Collectors.counting()));
String str = "programming";
Map<Character, Long> result =
str.chars()
.mapToObj(c -> (char)c)
.collect(Collectors.groupingBy(
Function.identity(),
Collectors.counting()));
class Employee{
int id;
String name;
String department;
double salary;
}
employees.stream()
.filter(e -> e.getSalary() > 50000)
.toList();
employees.stream()
.max(Comparator.comparing(Employee::getSalary))
.get();
employees.stream()
.collect(Collectors.averagingDouble(Employee::getSalary));
employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.counting()));
employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.maxBy(
Comparator.comparing(Employee::getSalary))));
employees.stream()
.sorted(Comparator.comparing(Employee::getSalary).reversed())
.skip(1)
.findFirst()
.get();
employees.stream()
.collect(Collectors.partitioningBy(
e -> e.getSalary() > 50000));

Difference:

Collector Purpose
groupingBy() Many groups
partitioningBy() Only true / false
list.stream()
.flatMap(List::stream)
.toList();
names.stream()
.max(Comparator.comparingInt(String::length))
.get();
names.stream()
.collect(Collectors.joining(","));
employees.stream()
.collect(Collectors.toMap(
Employee::getId,
Employee::getName));
map flatMap
One input → one output Many collections → one stream
int sum = nums.stream().reduce(0,Integer::sum);
nums.stream().collect(Collectors.toList());

Intermediate operations:

  • filter
  • map
  • sorted

Executed only after a terminal operation:

  • collect
  • count
  • findFirst
Stream<Integer> s = nums.stream();
s.count();
s.count(); // IllegalStateException
  • Race conditions
  • Thread contention
  • Order not guaranteed
  • Poor performance for small datasets

Real Interview Pattern: Latest 3 Products Per Category

Section titled “Real Interview Pattern: Latest 3 Products Per Category”
class Product {
private Long id;
private String name;
private String category;
private LocalDateTime createdDate;
}
Map<String, List<Product>> result =
products.stream()
.collect(Collectors.groupingBy(
Product::getCategory,
Collectors.collectingAndThen(
Collectors.toList(),
list -> list.stream()
.sorted(
Comparator.comparing(
Product::getCreatedDate)
.reversed())
.limit(3)
.toList()
)
));
flowchart LR
A[Products Stream] --> B[groupingBy Category]
B --> C[Convert each group to List]
C --> D[Sort by createdDate Desc]
D --> E[Limit to 3]
E --> F[Map Category -> Latest 3 Products]
Collectors.collectingAndThen(
Collectors.toList(),
list -> list.size()
)

Top 2 Highest Paid Employees per Department

Section titled “Top 2 Highest Paid Employees per Department”
employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.collectingAndThen(
Collectors.toList(),
list -> list.stream()
.sorted(
Comparator.comparing(Employee::getSalary)
.reversed())
.limit(2)
.toList()
)
));
employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.collectingAndThen(
Collectors.maxBy(
Comparator.comparing(Employee::getJoiningDate)),
Optional::get
)
));
employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.collectingAndThen(
Collectors.maxBy(
Comparator.comparing(Employee::getSalary)),
Optional::get
)
));
transactions.stream()
.collect(Collectors.groupingBy(
Transaction::getCustomerId,
Collectors.collectingAndThen(
Collectors.toList(),
list -> list.stream()
.sorted(
Comparator.comparing(Transaction::getAmount)
.reversed())
.limit(3)
.toList()
)
));
orders.stream()
.collect(Collectors.groupingBy(
Order::getCustomerId,
Collectors.collectingAndThen(
Collectors.maxBy(
Comparator.comparing(Order::getOrderDate)),
Optional::get
)
));
  • Department with highest average salary
  • Most expensive product in each category
  • Top 3 customers by purchase amount
  • Group employees by department and sort by salary descending
  • First non-repeated character
Problem Pattern
Top N per group groupingBy + sorted + limit
Highest/latest per group groupingBy + maxBy
Aggregation groupingBy + summing/averaging/counting
Duplicate detection groupingBy + counting
Nested collections flatMap
List to Map toMap
Ranking sorted + skip + findFirst

Character Frequency: Insertion Order and Duplicates

Section titled “Character Frequency: Insertion Order and Duplicates”
Map<Character, Long> frequencyMap =
str.chars()
.mapToObj(c -> (char) c)
.collect(Collectors.groupingBy(
Function.identity(),
LinkedHashMap::new,
Collectors.counting()));
frequencyMap.entrySet()
.stream()
.filter(entry -> entry.getValue() > 1)
.forEach(System.out::println);

Output (for "programming"):

r=2
g=2
m=2

Find Minimum and Maximum Value in an Array

Section titled “Find Minimum and Maximum Value in an Array”

Input

int[] arr = {10, 5, 20, 8, 15};
int min = Arrays.stream(arr)
.min()
.orElseThrow();
int max = Arrays.stream(arr)
.max()
.orElseThrow();

Using IntSummaryStatistics (Single Traversal)

Section titled “Using IntSummaryStatistics (Single Traversal)”
IntSummaryStatistics stats = Arrays.stream(arr)
.summaryStatistics();
System.out.println("Min: " + stats.getMin());
System.out.println("Max: " + stats.getMax());
int min = arr[0];
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
min = Math.min(min, arr[i]);
max = Math.max(max, arr[i]);
}
Approach Time Space Notes
Streams (min() and max()) O(n) O(1) Two traversals
summaryStatistics() O(n) O(1) Single traversal
Manual Loop O(n) O(1) Most efficient
  • Learn the reusable groupingBy + collectingAndThen pattern for Top-N questions.
  • Use maxBy for latest/highest record in each group.
  • Understand when to use map, flatMap, reduce, and collect.
  • Master sorting, grouping, aggregation, and ranking patterns.
  • Practice real-world business problems rather than only basic Stream APIs.
  • Prefer IntSummaryStatistics over separate min()/max() calls when both are needed, since it computes them in a single traversal.