Advanced Java Stream API

Juhilee NazareJuhilee Nazare
3 min read

In the previous article we’ve gained familiarity with various stream methods Java Stream API for Beginners. In this article, we’ll make use of these methods to solve real life problems and frequently asked interview questions.

Find duplicate elements in a list.

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.*;
import java.util.function.Function;

//In main method, create list and stream
List<Integer> nums = Arrays.asList(2, 7, 4, 3, 1, 7, 9, 2, 3);

Set<Integer> duplicateElements = nums.stream()
                                     .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))    //returns Map<Integer, Long>
                                     .entrySet()   //Set<Map.Entry<Integer, Long>>
                                     .stream()
                                     .filter(e -> e.getValue() > 1) //duplicate
                                     .map(Map.Entry::getKey)
                                     .collect(Collectors.toSet());

System.out.println(duplicateElements);     //[2, 3, 7]

Find employees with second highest salary.

public class Employee {
    private String empName;
    private double salary;

    public Employee(String empName, double salary) {
        this.empName = empName;
        this.salary = salary;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
}
List<Employee> employees = Arrays.asList(
    new Employee("Jui", 95000),
    new Employee("Alice", 80000),
    new Employee("Bob", 70000));

Optional<Double> secondHighestSalary = employees.stream()
                                                .map(Employee::getSalary)
                                                .distinct()
                                                .sorted(Comparator.reverseOrder())
                                                .skip(1)
                                                .findFirst();
//Find employees with 2nd highest salary
if(secondHighestSalary.isPresent()) {
   double targetSalary = secondHighestSalary.get();
   List<Employee> result = employees.stream()
                          .filter(e -> e.getSalary() == targetSalary)
                          .collect(Collectors.toList());

    result.forEach(System.out::println);
} else {
    System.out.println("Second highest salary not found");
}

Group employees by department.

List<Employee> employees = Arrays.asList(        //Modify Employee class by adding department
    new Employee("Jui", "IT"),
    new Employee("Alice", "HR"),
    new Employee("Bob", "HR"));

Map<String, List<Employee>> grouped = employees.stream()
                                      .collect(Collectors.groupingBy(Employee::getDepartment));

Count employees per department.

Map<String, Long> deptCount = employees.stream()
                                       .collect(Collectors.groupingBy(Employee::getDepartment), Collectors.counting());

Partition employees by salary > 50000.

Map<Boolean, List<Employee>> partitioned = employees.stream()
                                                    .collect(Collectors.partitioningBy(e -> e.getSalary() > 50000));

Sort employees by salary descending order.

employees.stream()
         .sorted(Compartor.comparing(Employee::getSalary).reversed())
         .forEach(e -> System.out.println(e.getName()));

Get top 3 highest paid employees.

List<Employee> topThree = employees.stream()
                                   .sorted(Compartor.comparing(Employee::getSalary).reversed())
                                   .limit(3)
                                   .collect(Collectors.toList());

Find first non-repeated character in a string.

String input = "swiss";
Optional<Character> firstNonRepeated = input.chars()  // IntStream
            .mapToObj(c -> (char) c)  // Convert to Stream<Character>
            .collect(Collectors.groupingBy(Function.identity(), LinkedHashMap::new, Collectors.counting()))  // preserve order
            .entrySet()
            .stream()
            .filter(entry -> entry.getValue() == 1)
            .map(Map.Entry::getKey)
            .findFirst();

System.out.println(firstNonRepeated.orElse(null));  // Output: 'w'

Calculate revenue per item category using formula revenue = price * quantity.

Given a class Item with name, quantity, price, category and a class Order with id, List <Item>.

// Sample data
List<Order> orders = Arrays.asList(
            new Order(1, Arrays.asList(
                new Item("Apple", 10, 1.5, "Fruits"),
                new Item("Banana", 5, 0.8, "Fruits"),
                new Item("Shampoo", 2, 5.0, "Personal Care")
            )),
            new Order(2, Arrays.asList(
                new Item("Toothpaste", 1, 3.0, "Personal Care"),
                new Item("Orange", 8, 1.2, "Fruits"),
                new Item("Soap", 3, 2.5, "Personal Care")
            ))
);

// Revenue per category = price * quantity
Map<String, Double> revenueByCategory = orders.stream()
            .flatMap(order -> order.getItems().stream()) // Stream<Item>
            .collect(Collectors.groupingBy(
                Item::getCategory,
                Collectors.summingDouble(Item::getRevenue)
            ));

// Print the result
revenueByCategory.forEach((category, revenue) ->
            System.out.println(category + " => $" + revenue));
1
Subscribe to my newsletter

Read articles from Juhilee Nazare directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Juhilee Nazare
Juhilee Nazare

I've 3.5+ years of experience in software development and willing to share my knowledge while working on real-time IT solutions.