Java 8 Stream Practice Problems with Solutions
Category 1: filter() - Filtering Operationsโ
1. Filter Even Numbersโ
Given a list of integers, filter and return only even numbers.
public static List<Integer> filterEvenNumbers(List<Integer> numbers) {
return numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
}
2. Filter Strings by Lengthโ
From a list of strings, filter strings that have length greater than 5.
public static List<String> filterStringsByLength(List<String> strings) {
return strings.stream()
.filter(s -> s.length() > 5)
.collect(Collectors.toList());
}
3. Filter Employees by Salaryโ
Given a list of Employee objects, filter employees whose salary is greater than 50000.
public static List<Employee> filterEmployeesBySalary(List<Employee> employees) {
return employees.stream()
.filter(e -> e.getSalary() > 50000)
.collect(Collectors.toList());
}
4. Filter Null Valuesโ
Remove all null values from a list of strings.
public static List<String> filterNullValues(List<String> strings) {
return strings.stream()
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
5. Filter by Multiple Conditionsโ
From a list of products, filter products where price > 100 AND category equals "Electronics".
public static List<Product> filterByMultipleConditions(List<Product> products) {
return products.stream()
.filter(p -> p.getPrice() > 100 && "Electronics".equals(p.getCategory()))
.collect(Collectors.toList());
}
6. Filter Distinct Prime Numbersโ
Filter prime numbers from a list and remove duplicates.
public static List<Integer> filterDistinctPrimeNumbers(List<Integer> numbers) {
return numbers.stream()
.filter(Java8StreamSolutions::isPrime)
.distinct()
.collect(Collectors.toList());
}
private static boolean isPrime(int n) {
if (n <= 1) return false;
if (n <= 3) return true;
if (n % 2 == 0 || n % 3 == 0) return false;
for (int i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) return false;
}
return true;
}
Category 2: map() - Transformation Operationsโ
7. Convert to Uppercaseโ
Convert all strings in a list to uppercase.
public static List<String> convertToUppercase(List<String> strings) {
return strings.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
}
8. Extract Propertyโ
From a list of Employee objects, extract and return a list of all employee names.
public static List<String> extractEmployeeNames(List<Employee> employees) {
return employees.stream()
.map(Employee::getName)
.collect(Collectors.toList());
}
9. Square Numbersโ
Given a list of integers, return a list with each number squared.
public static List<Integer> squareNumbers(List<Integer> numbers) {
return numbers.stream()
.map(n -> n * n)
.collect(Collectors.toList());
}
10. String to Lengthโ
Convert a list of strings to a list of their lengths.
public static List<Integer> stringToLength(List<String> strings) {
return strings.stream()
.map(String::length)
.collect(Collectors.toList());
}
11. Object Transformationโ
Convert a list of Employee objects to EmployeeDTO objects.
public static List<EmployeeDTO> transformToDTO(List<Employee> employees) {
return employees.stream()
.map(e -> new EmployeeDTO(e.getId(), e.getName(), e.getSalary()))
.collect(Collectors.toList());
}
12. Concatenate Prefixโ
Add a prefix "Mr. " to all names in a list.
public static List<String> concatenatePrefix(List<String> names) {
return names.stream()
.map(name -> "Mr. " + name)
.collect(Collectors.toList());
}
Category 3: flatMap() - Flattening Operationsโ
13. Flatten Nested Listsโ
Given a list of lists of integers, flatten it to a single list.
public static List<Integer> flattenNestedLists(List<List<Integer>> nestedLists) {
return nestedLists.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
}
14. Split and Flattenโ
From a list of sentences, split each into words and return all words as a single list.
public static List<String> splitAndFlatten(List<String> sentences) {
return sentences.stream()
.flatMap(s -> Arrays.stream(s.split("\\s+")))
.collect(Collectors.toList());
}
15. Flatten Object Collectionsโ
Given a list of Department objects (each containing a list of Employees), get all employees in a single list.
public static List<Employee> flattenDepartmentEmployees(List<Department> departments) {
return departments.stream()
.flatMap(d -> d.getEmployees().stream())
.collect(Collectors.toList());
}
16. Character Streamโ
Convert a list of strings into a stream of all individual characters.
public static List<Character> getCharacterStream(List<String> strings) {
return strings.stream()
.flatMap(s -> s.chars().mapToObj(c -> (char) c))
.collect(Collectors.toList());
}
17. Flatten Optional Valuesโ
Given a list of Optional<String>, flatten to get all present values.
public static List<String> flattenOptionals(List<Optional<String>> optionals) {
return optionals.stream()
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
}
Category 4: distinct() - Removing Duplicatesโ
18. Remove Duplicate Numbersโ
From a list of integers with duplicates, return unique values.
public static List<Integer> removeDuplicateNumbers(List<Integer> numbers) {
return numbers.stream()
.distinct()
.collect(Collectors.toList());
}
19. Unique Employee IDsโ
From a list of employees, get unique employee IDs.
public static List<Long> getUniqueEmployeeIds(List<Employee> employees) {
return employees.stream()
.map(Employee::getId)
.distinct()
.collect(Collectors.toList());
}
20. Case-Insensitive Unique Stringsโ
Get unique strings ignoring case sensitivity.
public static List<String> caseInsensitiveUnique(List<String> strings) {
return strings.stream()
.map(String::toLowerCase)
.distinct()
.collect(Collectors.toList());
}
Category 5: sorted() - Sorting Operationsโ
21. Sort Numbers Ascendingโ
Sort a list of integers in ascending order.
public static List<Integer> sortNumbersAscending(List<Integer> numbers) {
return numbers.stream()
.sorted()
.collect(Collectors.toList());
}
22. Sort Strings Descendingโ
Sort a list of strings in descending order.
public static List<String> sortStringsDescending(List<String> strings) {
return strings.stream()
.sorted(Comparator.reverseOrder())
.collect(Collectors.toList());
}
23. Sort by Multiple Fieldsโ
Sort employees first by department, then by salary within each department.
public static List<Employee> sortByMultipleFields(List<Employee> employees) {
return employees.stream()
.sorted(Comparator.comparing(Employee::getDepartment)
.thenComparing(Employee::getSalary))
.collect(Collectors.toList());
}
24. Sort by Custom Comparatorโ
Sort products by price in descending order, then by name alphabetically.
public static List<Product> sortByCustomComparator(List<Product> products) {
return products.stream()
.sorted(Comparator.comparing(Product::getPrice).reversed()
.thenComparing(Product::getName))
.collect(Collectors.toList());
}
25. Sort with Null Handlingโ
Sort a list of strings where some values might be null (nulls last).
public static List<String> sortWithNullHandling(List<String> strings) {
return strings.stream()
.sorted(Comparator.nullsLast(Comparator.naturalOrder()))
.collect(Collectors.toList());
}
Category 6: limit() & skip() - Pagination Operationsโ
26. Get First N Elementsโ
Return the first 5 elements from a list.
public static List<Integer> getFirstNElements(List<Integer> numbers) {
return numbers.stream()
.limit(5)
.collect(Collectors.toList());
}
27. Skip and Takeโ
Skip first 10 elements and take next 5 elements.
public static List<Integer> skipAndTake(List<Integer> numbers) {
return numbers.stream()
.skip(10)
.limit(5)
.collect(Collectors.toList());
}
28. Top 3 Salariesโ
Get the top 3 highest salaries from employee list.
public static List<Double> getTop3Salaries(List<Employee> employees) {
return employees.stream()
.map(Employee::getSalary)
.sorted(Comparator.reverseOrder())
.distinct()
.limit(3)
.collect(Collectors.toList());
}
29. Paginationโ
Implement pagination - get page 3 with page size 10.
public static List<Employee> getPaginatedResults(List<Employee> employees, int page, int pageSize) {
return employees.stream()
.skip((long) (page - 1) * pageSize)
.limit(pageSize)
.collect(Collectors.toList());
}
Category 7: peek() - Debugging Operationsโ
30. Debug Stream Pipelineโ
Use peek() to print each element while processing.
public static List<Integer> debugStreamPipeline(List<Integer> numbers) {
return numbers.stream()
.peek(n -> System.out.println("Original: " + n))
.filter(n -> n % 2 == 0)
.peek(n -> System.out.println("After filter: " + n))
.map(n -> n * 2)
.peek(n -> System.out.println("After map: " + n))
.collect(Collectors.toList());
}
31. Logging Transformationโ
Log each element before and after transformation.
public static List<String> loggingTransformation(List<String> strings) {
return strings.stream()
.peek(s -> System.out.println("Before: " + s))
.map(String::toUpperCase)
.peek(s -> System.out.println("After: " + s))
.collect(Collectors.toList());
}
Category 8: collect() - Collection Operationsโ
32. Collect to Listโ
Convert stream to ArrayList.
public static List<String> collectToList(Stream<String> stream) {
return stream.collect(Collectors.toCollection(ArrayList::new));
}
33. Collect to Setโ
Convert stream to HashSet to remove duplicates.
public static Set<Integer> collectToSet(List<Integer> numbers) {
return numbers.stream()
.collect(Collectors.toCollection(HashSet::new));
}
34. Collect to Mapโ
Convert list of employees to a Map with employeeId as key.
public static Map<Long, Employee> collectToMap(List<Employee> employees) {
return employees.stream()
.collect(Collectors.toMap(Employee::getId, e -> e));
}
35. Joining Stringsโ
Join all strings in a list with comma separator.
public static String joiningStrings(List<String> strings) {
return strings.stream()
.collect(Collectors.joining(", "));
}
36. Partitioningโ
Partition employees into two groups: salary > 50000 and salary <= 50000.
public static Map<Boolean, List<Employee>> partitionEmployees(List<Employee> employees) {
return employees.stream()
.collect(Collectors.partitioningBy(e -> e.getSalary() > 50000));
}
37. Grouping by Propertyโ
Group employees by their department.
public static Map<String, List<Employee>> groupByDepartment(List<Employee> employees) {
return employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
}
38. Grouping with Countingโ
Count number of employees in each department.
public static Map<String, Long> groupAndCount(List<Employee> employees) {
return employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment, Collectors.counting()));
}
39. Grouping with Sumโ
Calculate total salary by department.
public static Map<String, Double> groupAndSum(List<Employee> employees) {
return employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.summingDouble(Employee::getSalary)));
}
40. Multi-level Groupingโ
Group employees by department, then by city within each department.
public static Map<String, Map<String, List<Employee>>> multiLevelGrouping(List<Employee> employees) {
return employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.groupingBy(Employee::getCity)));
}
Category 9: reduce() - Reduction Operationsโ
41. Sum of Numbersโ
Calculate sum of all integers in a list using reduce.
public static int sumOfNumbers(List<Integer> numbers) {
return numbers.stream()
.reduce(0, Integer::sum);
}
42. Product of Numbersโ
Calculate product of all numbers.
public static int productOfNumbers(List<Integer> numbers) {
return numbers.stream()
.reduce(1, (a, b) -> a * b);
}
43. Concatenate Stringsโ
Concatenate all strings using reduce.
public static String concatenateStrings(List<String> strings) {
return strings.stream()
.reduce("", (a, b) -> a + b);
}
44. Find Maximumโ
Find maximum number using reduce.
public static Optional<Integer> findMaximum(List<Integer> numbers) {
return numbers.stream()
.reduce(Integer::max);
}
45. Find Minimum Salaryโ
Find employee with minimum salary using reduce.
public static Optional<Employee> findMinimumSalary(List<Employee> employees) {
return employees.stream()
.reduce((e1, e2) -> e1.getSalary() < e2.getSalary() ? e1 : e2);
}
46. Complex Reductionโ
Calculate total price of products after applying 10% discount.
public static double calculateTotalWithDiscount(List<Product> products) {
return products.stream()
.map(p -> p.getPrice() * 0.9)
.reduce(0.0, Double::sum);
}
Category 10: count() - Counting Operationsโ
47. Count Elementsโ
Count total number of elements in a stream.
public static long countElements(List<String> strings) {
return strings.stream()
.count();
}
48. Count After Filterโ
Count how many employees have salary > 50000.
public static long countAfterFilter(List<Employee> employees) {
return employees.stream()
.filter(e -> e.getSalary() > 50000)
.count();
}
49. Count Distinct Valuesโ
Count unique values in a list.
public static long countDistinctValues(List<Integer> numbers) {
return numbers.stream()
.distinct()
.count();
}
Category 11: anyMatch(), allMatch(), noneMatch()โ
50. Any Matchโ
Check if any employee has salary > 100000.
public static boolean anyMatchSalary(List<Employee> employees) {
return employees.stream()
.anyMatch(e -> e.getSalary() > 100000);
}
51. All Matchโ
Check if all products have price > 0.
public static boolean allMatchPrice(List<Product> products) {
return products.stream()
.allMatch(p -> p.getPrice() > 0);
}
52. None Matchโ
Check if no employee is below 18 years old.
public static boolean noneMatchAge(List<Employee> employees) {
return employees.stream()
.noneMatch(e -> e.getAge() < 18);
}
53. Multiple Conditionsโ
Check if any string starts with "A" and has length > 5.
public static boolean multipleConditionsMatch(List<String> strings) {
return strings.stream()
.anyMatch(s -> s.startsWith("A") && s.length() > 5);
}
Category 12: findFirst() & findAny()โ
54. Find First Elementโ
Get the first element from a stream.
public static Optional<String> findFirstElement(List<String> strings) {
return strings.stream()
.findFirst();
}
55. Find First After Filterโ
Find first employee with salary > 50000.
public static Optional<Employee> findFirstAfterFilter(List<Employee> employees) {
return employees.stream()
.filter(e -> e.getSalary() > 50000)
.findFirst();
}
56. Find Any in Parallelโ
Use findAny() in parallel stream.
public static Optional<Integer> findAnyInParallel(List<Integer> numbers) {
return numbers.parallelStream()
.filter(n -> n > 100)
.findAny();
}
57. Find First Even Numberโ
Find first even number greater than 100.
public static Optional<Integer> findFirstEven(List<Integer> numbers) {
return numbers.stream()
.filter(n -> n > 100 && n % 2 == 0)
.findFirst();
}
Category 13: min() & max()โ
58. Find Maximum Salaryโ
Find employee with maximum salary.
public static Optional<Employee> findMaxSalary(List<Employee> employees) {
return employees.stream()
.max(Comparator.comparing(Employee::getSalary));
}
59. Find Minimum Length Stringโ
Find shortest string in a list.
public static Optional<String> findMinLength(List<String> strings) {
return strings.stream()
.min(Comparator.comparing(String::length));
}
60. Find Max Using Custom Comparatorโ
Find oldest employee by date of birth.
public static Optional<Employee> findOldestEmployee(List<Employee> employees) {
return employees.stream()
.min(Comparator.comparing(Employee::getDateOfBirth));
}
Category 14: forEach() & forEachOrdered()โ
61. Print All Elementsโ
Print each element in the stream.
public static void printAllElements(List<String> strings) {
strings.stream()
.forEach(System.out::println);
}
62. Update Stateโ
Increase salary of all employees by 10% (use forEach).
public static void increaseSalary(List<Employee> employees) {
employees.forEach(e -> e.setSalary(e.getSalary() * 1.1));
}
63. Ordered Processingโ
Ensure elements are processed in order using forEachOrdered.
public static void orderedProcessing(List<Integer> numbers) {
numbers.parallelStream()
.forEachOrdered(System.out::println);
}
Category 15: toArray()โ
64. Convert to Arrayโ
Convert stream of strings to String array.
public static String[] convertToArray(List<String> strings) {
return strings.stream()
.toArray(String[]::new);
}
65. Convert to Integer Arrayโ
Convert list to Integer[] array.
public static Integer[] convertToIntegerArray(List<Integer> numbers) {
return numbers.stream()
.toArray(Integer[]::new);
}
Category 16: Numeric Stream Operationsโ
66. Sum Using IntStreamโ
Calculate sum using IntStream.sum().
public static int sumUsingIntStream(List<Integer> numbers) {
return numbers.stream()
.mapToInt(Integer::intValue)
.sum();
}
67. Average Calculationโ
Calculate average of numbers using average().
public static OptionalDouble calculateAverage(List<Integer> numbers) {
return numbers.stream()
.mapToInt(Integer::intValue)
.average();
}
68. Range Generationโ
Generate numbers from 1 to 100 using IntStream.range().
public static List<Integer> generateRange() {
return IntStream.rangeClosed(1, 100)
.boxed()
.collect(Collectors.toList());
}
69. Statisticsโ
Get max, min, average, sum in one go using summaryStatistics().
public static IntSummaryStatistics getStatistics(List<Integer> numbers) {
return numbers.stream()
.mapToInt(Integer::intValue)
.summaryStatistics();
}
70. Map to Intโ
Convert list of strings to IntStream of their lengths and find sum.
public static int sumOfLengths(List<String> strings) {
return strings.stream()
.mapToInt(String::length)
.sum();
}
Category 17: Parallel Streamsโ
71. Parallel Processingโ
Convert sequential stream to parallel and compare performance.
public static List<Integer> parallelProcessing(List<Integer> numbers) {
return numbers.parallelStream()
.map(n -> n * 2)
.collect(Collectors.toList());
}
72. Parallel Sumโ
Calculate sum of large list using parallel stream.
public static int parallelSum(List<Integer> numbers) {
return numbers.parallelStream()
.mapToInt(Integer::intValue)
.sum();
}
73. Thread Safetyโ
Demonstrate thread-safety issues with parallel streams.
public static List<Integer> threadSafetyDemo(List<Integer> numbers) {
// Thread-safe approach
return numbers.parallelStream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
}
Category 18: Optional Operationsโ
74. Handle Empty Streamโ
Use Optional to handle empty stream results.
public static String handleEmptyStream(List<String> strings) {
return strings.stream()
.findFirst()
.orElse("Default Value");
}
75. Optional with orElseโ
Find employee by ID, return default if not found.
public static Employee findEmployeeById(List<Employee> employees, Long id) {
return employees.stream()
.filter(e -> e.getId().equals(id))
.findFirst()
.orElse(new Employee());
}
76. Optional Chainingโ
Use Optional with map and flatMap.
public static Optional<String> optionalChaining(List<Employee> employees, Long id) {
return employees.stream()
.filter(e -> e.getId().equals(id))
.findFirst()
.map(Employee::getDepartment)
.map(String::toUpperCase);
}
Category 19: Collectors Advancedโ
77. Collectors.toMap with Merge Functionโ
Handle duplicate keys while collecting to map.
public static Map<String, Employee> toMapWithMerge(List<Employee> employees) {
return employees.stream()
.collect(Collectors.toMap(
Employee::getDepartment,
e -> e,
(e1, e2) -> e1.getSalary() > e2.getSalary() ? e1 : e2));
}
78. Downstream Collectorsโ
Group by department and get max salary in each.
public static Map<String, Optional<Employee>> downstreamCollectors(List<Employee> employees) {
return employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.maxBy(Comparator.comparing(Employee::getSalary))));
}
79. Mapping Collectorโ
Group employees by department and collect only their names.
public static Map<String, List<String>> mappingCollector(List<Employee> employees) {
return employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.mapping(Employee::getName, Collectors.toList())));
}
80. Custom Collectorโ
Create a custom collector to calculate median.
public static double calculateMedian(List<Integer> numbers) {
List<Integer> sorted = numbers.stream()
.sorted()
.collect(Collectors.toList());
int size = sorted.size();
if (size % 2 == 0) {
return (sorted.get(size / 2 - 1) + sorted.get(size / 2)) / 2.0;
} else {
return sorted.get(size / 2);
}
}
Category 20: Complex Real-World Problemsโ
81. Second Highest Salaryโ
Find second highest salary from employee list.
public static Optional<Double> secondHighestSalary(List<Employee> employees) {
return employees.stream()
.map(Employee::getSalary)
.distinct()
.sorted(Comparator.reverseOrder())
.skip(1)
.findFirst();
}
82. Most Frequent Elementโ
Find the most frequently occurring element in a list.
public static Optional<Integer> mostFrequentElement(List<Integer> numbers) {
return numbers.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet().stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey);
}
83. Remove Duplicates Preserve Orderโ
Remove duplicates while maintaining insertion order.
public static List<Integer> removeDuplicatesPreserveOrder(List<Integer> numbers) {
return numbers.stream()
.distinct()
.collect(Collectors.toList());
}
84. Anagram Groupingโ
Group strings that are anagrams of each other.
public static Map<String, List<String>> groupAnagrams(List<String> strings) {
return strings.stream()
.collect(Collectors.groupingBy(s -> {
char[] chars = s.toCharArray();
Arrays.sort(chars);
return new String(chars);
}));
}
85. Duplicate Elementsโ
Find all duplicate elements in a list.
public static List<Integer> findDuplicates(List<Integer> numbers) {
return numbers.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet().stream()
.filter(e -> e.getValue() > 1)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
86. Nth Highest Elementโ
Find nth highest salary (generic solution).
public static Optional<Double> nthHighestSalary(List<Employee> employees, int n) {
return employees.stream()
.map(Employee::getSalary)
.distinct()
.sorted(Comparator.reverseOrder())
.skip(n - 1)
.findFirst();
}
87. Merge Two Listsโ
Merge two lists and remove duplicates.
public static List<Integer> mergeLists(List<Integer> list1, List<Integer> list2) {
return Stream.concat(list1.stream(), list2.stream())
.distinct()
.collect(Collectors.toList());
}
88. Department with Max Employeesโ
Find department with maximum number of employees.
public static Optional<String> departmentWithMaxEmployees(List<Employee> employees) {
return employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment, Collectors.counting()))
.entrySet().stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey);
}
89. String Frequency Mapโ
Create a map of each string and its frequency count.
public static Map<String, Long> stringFrequencyMap(List<String> strings) {
return strings.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
}
90. Employee with Longest Nameโ
Find employee with the longest name in each department.
public static Map<String, Optional<Employee>> longestNameByDepartment(List<Employee> employees) {
return employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.maxBy(Comparator.comparing(e -> e.getName().length()))));
}
91. Cumulative Sumโ
Create a list of cumulative sums from original list.
public static List<Integer> cumulativeSum(List<Integer> numbers) {
return numbers.stream()
.collect(() -> new ArrayList<Integer>(),
(list, n) -> {
int sum = list.isEmpty() ? n : list.get(list.size() - 1) + n;
list.add(sum);
},
ArrayList::addAll);
}
92. Intersection of Listsโ
Find common elements between two lists.
public static List<Integer> findIntersection(List<Integer> list1, List<Integer> list2) {
return list1.stream()
.filter(list2::contains)
.distinct()
.collect(Collectors.toList());
}
93. Partition and Transformโ
Partition list into two groups and apply different transformations.
public static Map<Boolean, List<Integer>> partitionAndTransform(List<Integer> numbers) {
Map<Boolean, List<Integer>> partitioned = numbers.stream()
.collect(Collectors.partitioningBy(n -> n % 2 == 0));
// Transform even numbers (multiply by 2)
partitioned.put(true, partitioned.get(true).stream()
.map(n -> n * 2)
.collect(Collectors.toList()));
// Transform odd numbers (add 1)
partitioned.put(false, partitioned.get(false).stream()
.map(n -> n + 1)
.collect(Collectors.toList()));
return partitioned;
}
94. Reverse Each Wordโ
Reverse each word in a sentence while maintaining word order.
public static String reverseEachWord(String sentence) {
return Arrays.stream(sentence.split("\\s+"))
.map(word -> new StringBuilder(word).reverse().toString())
.collect(Collectors.joining(" "));
}
95. Find Missing Numbersโ
Find missing numbers in a sequence from 1 to N.
public static List<Integer> findMissingNumbers(List<Integer> numbers, int n) {
Set<Integer> numSet = new HashSet<>(numbers);
return IntStream.rangeClosed(1, n)
.filter(i -> !numSet.contains(i))
.boxed()
.collect(Collectors.toList());
}
96. Age Group Classificationโ
Classify employees into age groups (18-30, 31-50, 51+).
public static Map<String, List<Employee>> classifyByAgeGroup(List<Employee> employees) {
return employees.stream()
.collect(Collectors.groupingBy(e -> {
int age = e.getAge();
if (age <= 30) return "18-30";
else if (age <= 50) return "31-50";
else return "51+";
}));
}
97. Calculate Percentileโ
Calculate 90th percentile of salaries.
public static double calculate90thPercentile(List<Employee> employees) {
List<Double> sortedSalaries = employees.stream()
.map(Employee::getSalary)
.sorted()
.collect(Collectors.toList());
int index = (int) Math.ceil(0.90 * sortedSalaries.size()) - 1;
return sortedSalaries.get(index);
}
98. Rolling Averageโ
Calculate rolling average of last 3 elements.
public static List<Double> rollingAverage(List<Integer> numbers, int windowSize) {
return IntStream.range(0, numbers.size())
.filter(i -> i >= windowSize - 1)
.mapToObj(i -> {
double sum = 0;
for (int j = 0; j < windowSize; j++) {
sum += numbers.get(i - j);
}
return sum / windowSize;
})
.collect(Collectors.toList());
}
99. Pair Sum Targetโ
Find pairs of numbers that sum to a target value.
public static List<int[]> findPairsWithSum(List<Integer> numbers, int target) {
Set<Integer> seen = new HashSet<>();
return numbers.stream()
.filter(n -> {
int complement = target - n;
if (seen.contains(complement)) {
return true;
}
seen.add(n);
return false;
})
.map(n -> new int[]{target - n, n})
.collect(Collectors.toList());
}
100. Hierarchical Groupingโ
Create hierarchical grouping: Country -> State -> City -> Employees.
public static Map<String, Map<String, Map<String, List<Employee>>>> hierarchicalGrouping(
List<Employee> employees) {
return employees.stream()
.collect(Collectors.groupingBy(
Employee::getCountry,
Collectors.groupingBy(
Employee::getState,
Collectors.groupingBy(Employee::getCity))));
}
Supporting Classesโ
// Employee Class
class Employee {
private Long id;
private String name;
private double salary;
private String department;
private String city;
private String state;
private String country;
private int age;
private LocalDate dateOfBirth;
// Constructors
public Employee() {}
public Employee(Long id, String name, double salary, String department) {
this.id = id;
this.name = name;
this.salary = salary;
this.department = department;
}
// Getters and Setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public double getSalary() { return salary; }
public void setSalary(double salary) { this.salary = salary; }
public String getDepartment() { return department; }
public void setDepartment(String department) { this.department = department; }
public String getCity() { return city; }
public void setCity(String city) { this.city = city; }
public String getState() { return state; }
public void setState(String state) { this.state = state; }
public String getCountry() { return country; }
public void setCountry(String country) { this.country = country; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public LocalDate getDateOfBirth() { return dateOfBirth; }
public void setDateOfBirth(LocalDate dateOfBirth) { this.dateOfBirth = dateOfBirth; }
}
// EmployeeDTO Class
class EmployeeDTO {
private Long id;
private String name;
private double salary;
public EmployeeDTO(Long id, String name, double salary) {
this.id = id;
this.name = name;
this.salary = salary;
}
// Getters and Setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public double getSalary() { return salary; }
public void setSalary(double salary) { this.salary = salary; }
}
// Product Class
class Product {
private Long id;
private String name;
private double price;
private String category;
public Product() {}
public Product(Long id, String name, double price, String category) {
this.id = id;
this.name = name;
this.price = price;
this.category = category;
}
// Getters and Setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public double getPrice() { return price; }
public void setPrice(double price) { this.price = price; }
public String getCategory() { return category; }
public void setCategory(String category) { this.category = category; }
}
// Department Class
class Department {
private Long id;
private String name;
private List<Employee> employees;
public Department() {
this.employees = new ArrayList<>();
}
public Department(Long id, String name, List<Employee> employees) {
this.id = id;
this.name = name;
this.employees = employees;
}
// Getters and Setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public List<Employee> getEmployees() { return employees; }
public void setEmployees(List<Employee> employees) { this.employees = employees; }
}
Bonus: Interview Favorites Solutionsโ
Find First Non-Repeated Characterโ
public static Optional<Character> findFirstNonRepeatedChar(String str) {
Map<Character, Long> charCount = str.chars()
.mapToObj(c -> (char) c)
.collect(Collectors.groupingBy(Function.identity(),
LinkedHashMap::new, Collectors.counting()));
return charCount.entrySet().stream()
.filter(e -> e.getValue() == 1)
.map(Map.Entry::getKey)
.findFirst();
}
Sort Map by Valuesโ
public static Map<String, Integer> sortMapByValues(Map<String, Integer> map) {
return map.entrySet().stream()
.sorted(Map.Entry.comparingByValue())
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(e1, e2) -> e1,
LinkedHashMap::new));
}
Calculate Running Totalโ
public static List<Integer> calculateRunningTotal(List<Integer> numbers) {
List<Integer> result = new ArrayList<>();
numbers.stream()
.reduce(0, (sum, n) -> {
int newSum = sum + n;
result.add(newSum);
return newSum;
});
return result;
}
Find Elements That Appear Onceโ
public static List<Integer> findElementsAppearingOnce(List<Integer> numbers) {
return numbers.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet().stream()
.filter(e -> e.getValue() == 1)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
Convert List to Map with Indexโ
public static Map<Integer, String> listToMapWithIndex(List<String> list) {
return IntStream.range(0, list.size())
.boxed()
.collect(Collectors.toMap(
i -> i,
list::get));
}
Usage Examplesโ
public class Main {
public static void main(String[] args) {
// Example 1: Filter Even Numbers
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> evenNumbers = filterEvenNumbers(numbers);
System.out.println("Even numbers: " + evenNumbers);
// Example 2: Group Employees by Department
List<Employee> employees = Arrays.asList(
new Employee(1L, "John", 60000, "IT"),
new Employee(2L, "Jane", 75000, "HR"),
new Employee(3L, "Bob", 55000, "IT"),
new Employee(4L, "Alice", 80000, "HR")
);
Map<String, List<Employee>> groupedByDept = groupByDepartment(employees);
System.out.println("Employees by department: " + groupedByDept);
// Example 3: Second Highest Salary
Optional<Double> secondHighest = secondHighestSalary(employees);
secondHighest.ifPresent(salary ->
System.out.println("Second highest salary: " + salary));
// Example 4: Find Duplicates
List<Integer> numbersWithDuplicates = Arrays.asList(1, 2, 3, 2, 4, 5, 3, 6);
List<Integer> duplicates = findDuplicates(numbersWithDuplicates);
System.out.println("Duplicates: " + duplicates);
// Example 5: String Frequency
List<String> words = Arrays.asList("apple", "banana", "apple", "cherry", "banana");
Map<String, Long> frequency = stringFrequencyMap(words);
System.out.println("Word frequency: " + frequency);
}
}
Key Takeawaysโ
- filter() - Use for filtering elements based on conditions
- map() - Use for transforming elements
- flatMap() - Use for flattening nested structures
- collect() - Terminal operation to gather results
- reduce() - For aggregation operations
- Collectors - Powerful utility for complex collection operations
- Optional - Handle null safely
- Parallel Streams - For performance with large datasets
- Method References - Clean and readable code
- Chaining - Combine multiple operations for complex logic
Performance Tipsโ
- Use parallel streams for large datasets (10,000+ elements)
- Avoid unnecessary boxing/unboxing - use primitive streams when possible
- Short-circuit operations (findFirst, anyMatch) can improve performance
- Stateless operations are preferred for parallel processing
- Consider memory overhead of intermediate collections
- Use method references over lambdas when possible for better performance
Common Pitfalls to Avoidโ
- Modifying source while streaming
- Using forEach for accumulation (use reduce or collect instead)
- Ignoring null values without filtering
- Not handling empty streams properly
- Overusing parallel streams for small datasets
- Creating unnecessary intermediate collections
- Using peek() for business logic (it's for debugging only)
Interview Tipsโ
- Always consider edge cases (empty lists, null values)
- Explain time and space complexity
- Mention alternatives (traditional loops vs streams)
- Discuss when NOT to use streams (simple iterations, performance-critical code)
- Be prepared to optimize your solution
- Know the difference between intermediate and terminal operations
- Understand lazy evaluation in streams