Part-I : Stream API Coding Questions
Created on: Sep 18, 2024
Streams are commonly used in Java projects to simplify complex logic and reduce the amount of code needed. This blog will illustrate a list of problems that can be effectively solved using streams.
Before we proceed, let’s review some important methods available in the Stream API.
- map: The map() operation is used to transform the elements of a stream by applying a given function to each element. It takes a lambda expression or method reference as an argument, which defines the transformation to be applied. The map() operation returns a new stream consisting of the transformed elements.
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
- groupingBy The groupingBy() method of Collectors class in Java are used for grouping objects by some property and storing results in a Map instance.This method provides similar functionality to SQL’s GROUP BY clause.
public static <T, K, A, D> Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream) { return groupingBy(classifier, HashMap::new, downstream); }
-
distinct():
Operation is used to eliminate duplicate elements from a stream.The time complexity of distinct() can vary depending on the size of the stream and the nature of the elements being compared. If the stream has n elements and the comparison of elements takes constant time (O(1)), the time complexity of distinct() can be considered to be O(n). However, if the comparison of elements takes time proportional to the size of the stream (O(n)), the time complexity of distinct() can be considered to be O(n^2).
The actual implementation of distinct() may use various data structures and algorithms to optimize the removal of duplicates. For example, it may use a HashSet or a TreeSet to store the encountered elements and perform efficient uniqueness checks. These data structures have their own time complexities for insertion and lookup operations, which can influence the overall time complexity of distinct().
-
max()
The max() method is used to find the maximum element in a stream based on a given comparator. It returns an Optional<T> object that represents the maximum element, or an empty Optional if the stream is empty.
The time complexity of the
max()
operation in the Stream API depends on the characteristics of the underlying stream source and the provided comparator (if any).In summary, the time complexity of the
max()
operation in the Stream API is typically O(n) for sequential streams and O(n / p) for parallel streams, where n is the number of elements and p is the level of parallelism. -
minBy():
In Java 8, the minBy collector is used to find the minimum element in a stream based on a specified comparator. It returns an Optional containing the minimum element, or an empty Optional if the stream is empty.
public static <T> Collector<T, ?, Optional<T>> minBy(Comparator<? super T> comparator)
-
entrySet()
.entrySet() method of the Map interface to obtain a Set of key-value pairs, and then use the Stream API to perform various operations on those entries.
-
toMap
In Java, the Collectors.toMap() method is a convenient way to collect elements from a stream into a Map based on specified keys and values.
The toMap() method has multiple overloaded versions, but the most commonly used version takes two lambda expressions: one to extract the key from each element and another to extract the value from each element.
-
mapping
It is used to apply a transformation to the elements of a stream before collecting them into another collection.
public static <T, U, A, R> Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper, Collector<? super U, A, R> downstream)
Now let’s practice. You can perform the following exercises in any editor of your choice, such as IntelliJ, Eclipse, or another IDE. Let's start by creating a Employee
class.
public class Employee { int id; String name; int age; String gender; String department; int yearOfJoining; double salary; public Employee(int id, String name, int age, String gender, String department, int yearOfJoining, double salary) { this.id = id; this.name = name; this.age = age; this.gender = gender; this.department = department; this.yearOfJoining = yearOfJoining; this.salary = salary; } public int getId() { return id; } public String getName() { return name; } public int getAge() { return age; } public String getGender() { return gender; } public String getDepartment() { return department; } public int getYearOfJoining() { return yearOfJoining; } public double getSalary() { return salary; } @Override public String toString() { return "Id : " + id + ", Name : " + name + ", age : " + age + ", Gender : " + gender + ", Department : " + department + ", Year Of Joining : " + yearOfJoining + ", Salary : " + salary; } }
Create a list of employee.
public class EmployeeCollection { static List<Employee> employeeList = new ArrayList<Employee>(); static { employeeList.add(new Employee(111, "Jiya Brein", 32, "Female", "HR", 2011, 25000.0)); employeeList.add(new Employee(122, "Paul Niksui", 25, "Male", "Sales And Marketing", 2015, 13500.0)); employeeList.add(new Employee(133, "Martin Theron", 29, "Male", "Infrastructure", 2012, 18000.0)); employeeList.add(new Employee(144, "Murali Gowda", 28, "Male", "Product Development", 2014, 32500.0)); employeeList.add(new Employee(155, "Nima Roy", 27, "Female", "HR", 2013, 22700.0)); employeeList.add(new Employee(166, "Iqbal Hussain", 43, "Male", "Security And Transport", 2016, 10500.0)); employeeList.add(new Employee(177, "Manu Sharma", 35, "Male", "Account And Finance", 2010, 27000.0)); employeeList.add(new Employee(188, "Wang Liu", 31, "Male", "Product Development", 2015, 34500.0)); employeeList.add(new Employee(199, "Amelia Zoe", 24, "Female", "Sales And Marketing", 2016, 11500.0)); employeeList.add(new Employee(200, "Jaden Dough", 38, "Male", "Security And Transport", 2015, 11000.5)); employeeList.add(new Employee(211, "Jasna Kaur", 27, "Female", "Infrastructure", 2014, 15700.0)); employeeList.add(new Employee(222, "Nitin Joshi", 25, "Male", "Product Development", 2016, 28200.0)); employeeList.add(new Employee(233, "Jyothi Reddy", 27, "Female", "Account And Finance", 2013, 21300.0)); employeeList.add(new Employee(244, "Nicolus Den", 24, "Male", "Sales And Marketing", 2017, 10700.5)); employeeList.add(new Employee(255, "Ali Baig", 23, "Male", "Infrastructure", 2018, 12700.0)); employeeList.add(new Employee(266, "Sanvi Pandey", 26, "Female", "Product Development", 2015, 28900.0)); employeeList.add(new Employee(277, "Anuj Chettiar", 31, "Male", "Product Development", 2012, 35700.0)); } }
Now let's start with question.
- How many male and female employees are there in the organization
public static void main(String[] args) { List<Employee> employees = EmployeeCollection.employeeList; Map<String, Long> genderCount = employees.stream().collect(Collectors.groupingBy(Employee::getGender, Collectors.counting())); System.out.println(genderCount); }
{Male=11, Female=6}
- Print the name of all departments in the organization
List<String> departmentList = employees.stream() .map(Employee::getDepartment) .distinct() .collect(Collectors.toList()); System.out.println(departmentList);
[HR, Sales And Marketing, Infrastructure, Product Development, Security And Transport, Account And Finance]
- What is the average age of male and female employees?
import java.text.DecimalFormat; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class EmployeeQuery { public static void main(String[] args) { List<Employee> employees = EmployeeCollection.employeeList; Map<String, Double> averageAgeGender = employees.stream() .collect(Collectors.groupingBy(Employee::getGender, Collectors.averagingInt(Employee::getAge))); DecimalFormat decimalFormat = new DecimalFormat("#.##"); averageAgeGender.forEach((gender, avgAge) -> System.out.println("Avg of " + gender + " = " + decimalFormat.format(avgAge))); } }
Avg of Male = 30.18 Avg of Female = 27.17
- Get the details of highest paid employee in the organization?
Employee maxSalaryEmployee = employees.stream() .max(Comparator.comparingDouble(Employee::getSalary)) .orElseThrow( ()->new RuntimeException("No such employee exist")); System.out.println(maxSalaryEmployee);
Id : 277, Name : Anuj Chettiar, age : 31, Gender : Male, Department : Product Development, Year Of Joining : 2012, Salary : 35700.0
- Get the names of all employees who have joined after 2015?
List<Employee> joinedafter2015 = employees.stream() .filter(employee -> employee.yearOfJoining>2015) .collect(Collectors.toList()); System.out.println(joinedafter2015);
[Id : 166, Name : Iqbal Hussain, age : 43, Gender : Male, Department : Security And Transport, Year Of Joining : 2016, Salary : 10500.0, Id : 199, Name : Amelia Zoe, age : 24, Gender : Female, Department : Sales And Marketing, Year Of Joining : 2016, Salary : 11500.0, Id : 222, Name : Nitin Joshi, age : 25, Gender : Male, Department : Product Development, Year Of Joining : 2016, Salary : 28200.0, Id : 244, Name : Nicolus Den, age : 24, Gender : Male, Department : Sales And Marketing, Year Of Joining : 2017, Salary : 10700.5, Id : 255, Name : Ali Baig, age : 23, Gender : Male, Department : Infrastructure, Year Of Joining : 2018, Salary : 12700.0]
- Count the number of employees in each department?
Map<String, Long> employeeInEachDept = employees.stream() .collect(Collectors.groupingBy(Employee::getDepartment, Collectors.counting())); System.out.println(employeeInEachDept);
{Product Development=5, Security And Transport=2, Sales And Marketing=3, Infrastructure=3, HR=2, Account And Finance=2}
- Get the details of youngest male employee in the each department ?
Map<String, Employee> minAgeMaleEmployee = employees.stream() .filter(employee -> employee.gender == "Male") .collect(Collectors.groupingBy(Employee::getDepartment, Collectors.minBy(Comparator.comparingInt(Employee::getAge)))) .entrySet().stream() .filter(entry -> entry.getValue().isPresent() == true) .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().get())); System.out.println(minAgeMaleEmployee);
{Product Development=Id : 222, Name : Nitin Joshi, age : 25, Gender : Male, Department : Product Development, Year Of Joining : 2016, Salary : 28200.0, Security And Transport=Id : 200, Name : Jaden Dough, age : 38, Gender : Male, Department : Security And Transport, Year Of Joining : 2015, Salary : 11000.5, Sales And Marketing=Id : 244, Name : Nicolus Den, age : 24, Gender : Male, Department : Sales And Marketing, Year Of Joining : 2017, Salary : 10700.5, Infrastructure=Id : 255, Name : Ali Baig, age : 23, Gender : Male, Department : Infrastructure, Year Of Joining : 2018, Salary : 12700.0, Account And Finance=Id : 177, Name : Manu Sharma, age : 35, Gender : Male, Department : Account And Finance, Year Of Joining : 2010, Salary : 27000.0}
- Employee with most working experience in the organization
Employee mostExperiancedEmployee = employees.stream() .min(Comparator.comparingInt(Employee::getYearOfJoining)) .orElseThrow(()-> new RuntimeException("No such employee")); System.out.println(mostExperiancedEmployee);
Id : 177, Name : Manu Sharma, age : 35, Gender : Male, Department : Account And Finance, Year Of Joining : 2010, Salary : 27000.0
- How many male and female employees are there in the sales and marketing team
Map<String, Long> genderCountInSalesMarketing = employees.stream() .filter(employee -> employee.getDepartment()=="Sales And Marketing") .collect(Collectors.groupingBy(Employee::getGender, Collectors.counting())); System.out.println(genderCountInSalesMarketing);
{Female=1, Male=2}
- List down the names of all employees in each department?
Map<String, List<String>> employeeNamePerDept = employees.stream() .collect(Collectors.groupingBy(Employee::getDepartment, Collectors.mapping(Employee::getName, Collectors.toList()))); System.out.println(employeeNamePerDept);
{Product Development=[Murali Gowda, Wang Liu, Nitin Joshi, Sanvi Pandey, Anuj Chettiar], Security And Transport=[Iqbal Hussain, Jaden Dough], Sales And Marketing=[Paul Niksui, Amelia Zoe, Nicolus Den], Infrastructure=[Martin Theron, Jasna Kaur, Ali Baig], HR=[Jiya Brein, Nima Roy], Account And Finance=[Manu Sharma, Jyothi Reddy]}
- What is the average salary and total salary of the whole organization?
double averageSalary = employees.stream() .mapToDouble(Employee::getSalary) .average() .orElse(0); double totalSalary = employees.stream() .mapToDouble(Employee::getSalary) .sum(); System.out.println(averageSalary); System.out.println(totalSalary);
21141.235294117647 359401.0
- Separate the employees who are younger or equal to 25 years from those employees who are older than 25 years.
List<Employee> employeesWithAgeLessThan25 = employees.stream() .filter(employee -> employee.getAge() <= 25) .collect(Collectors.toList()); System.out.println(employeesWithAgeLessThan25);
[Id : 122, Name : Paul Niksui, age : 25, Gender : Male, Department : Sales And Marketing, Year Of Joining : 2015, Salary : 13500.0, Id : 199, Name : Amelia Zoe, age : 24, Gender : Female, Department : Sales And Marketing, Year Of Joining : 2016, Salary : 11500.0, Id : 222, Name : Nitin Joshi, age : 25, Gender : Male, Department : Product Development, Year Of Joining : 2016, Salary : 28200.0, Id : 244, Name : Nicolus Den, age : 24, Gender : Male, Department : Sales And Marketing, Year Of Joining : 2017, Salary : 10700.5, Id : 255, Name : Ali Baig, age : 23, Gender : Male, Department : Infrastructure, Year Of Joining : 2018, Salary : 12700.0]
- Who is the oldest employee in the organization? What is his age and which department he belongs to?
Employee oldestEmployee = employees.stream() .max(Comparator.comparingInt(Employee::getAge)) .orElse(null); System.out.println(oldestEmployee);
Id : 166, Name : Iqbal Hussain, age : 43, Gender : Male, Department : Security And Transport, Year Of Joining : 2016, Salary : 10500.0
- Increase the salary of each employee by 100
List<Employee> employeeWithSalaryIncrement = employees.stream() .map(employee -> new Employee(employee.id, employee.name, employee.age, employee.gender, employee.department, employee.yearOfJoining, employee.salary+100)) .collect(Collectors.toList()); System.out.println(employeeWithSalaryIncrement);
[Id : 111, Name : Jiya Brein, age : 32, Gender : Female, Department : HR, Year Of Joining : 2011, Salary : 25100.0, Id : 122, Name : Paul Niksui, age : 25, Gender : Male, Department : Sales And Marketing, Year Of Joining : 2015, Salary : 13600.0, Id : 133, Name : Martin Theron, age : 29, Gender : Male, Department : Infrastructure, Year Of Joining : 2012, Salary : 18100.0, Id : 144, Name : Murali Gowda, age : 28, Gender : Male, Department : Product Development, Year Of Joining : 2014, Salary : 32600.0, Id : 155, Name : Nima Roy, age : 27, Gender : Female, Department : HR, Year Of Joining : 2013, Salary : 22800.0, Id : 166, Name : Iqbal Hussain, age : 43, Gender : Male, Department : Security And Transport, Year Of Joining : 2016, Salary : 10600.0, Id : 177, Name : Manu Sharma, age : 35, Gender : Male, Department : Account And Finance, Year Of Joining : 2010, Salary : 27100.0, Id : 188, Name : Wang Liu, age : 31, Gender : Male, Department : Product Development, Year Of Joining : 2015, Salary : 34600.0, Id : 199, Name : Amelia Zoe, age : 24, Gender : Female, Department : Sales And Marketing, Year Of Joining : 2016, Salary : 11600.0, Id : 200, Name : Jaden Dough, age : 38, Gender : Male, Department : Security And Transport, Year Of Joining : 2015, Salary : 11100.5, Id : 211, Name : Jasna Kaur, age : 27, Gender : Female, Department : Infrastructure, Year Of Joining : 2014, Salary : 15800.0, Id : 222, Name : Nitin Joshi, age : 25, Gender : Male, Department : Product Development, Year Of Joining : 2016, Salary : 28300.0, Id : 233, Name : Jyothi Reddy, age : 27, Gender : Female, Department : Account And Finance, Year Of Joining : 2013, Salary : 21400.0, Id : 244, Name : Nicolus Den, age : 24, Gender : Male, Department : Sales And Marketing, Year Of Joining : 2017, Salary : 10800.5, Id : 255, Name : Ali Baig, age : 23, Gender : Male, Department : Infrastructure, Year Of Joining : 2018, Salary : 12800.0, Id : 266, Name : Sanvi Pandey, age : 26, Gender : Female, Department : Product Development, Year Of Joining : 2015, Salary : 29000.0, Id : 277, Name : Anuj Chettiar, age : 31, Gender : Male, Department : Product Development, Year Of Joining : 2012, Salary : 35800.0]
- Get a employee with id = 111
Optional<Employee> employeeSearch = employees.stream() .filter(employee -> employee.getId() == 111) .findFirst(); System.out.println(employeeSearch);
Optional[Id : 111, Name : Jiya Brein, age : 32, Gender : Female, Department : HR, Year Of Joining : 2011, Salary : 25000.0]
16 employee with second highest salary
Employee employee = employees.stream() .sorted(Comparator.comparing(Employee::getSalary).reversed()) .skip(1).findFirst().get(); System.out.println(employee);
Id : 188, Name : Wang Liu, age : 31, Gender : Male, Department : Product Development, Year Of Joining : 2015, Salary : 34500.0
- Sort the employee with the salary they earn
List<Employee> sortedEmployeeBySalary = employees.stream().sorted(Comparator.comparing(Employee::getSalary)) .collect(Collectors.toList()); System.out.println(sortedEmployeeBySalary);
[Id : 166, Name : Iqbal Hussain, age : 43, Gender : Male, Department : Security And Transport, Year Of Joining : 2016, Salary : 10500.0, Id : 244, Name : Nicolus Den, age : 24, Gender : Male, Department : Sales And Marketing, Year Of Joining : 2017, Salary : 10700.5, Id : 200, Name : Jaden Dough, age : 38, Gender : Male, Department : Security And Transport, Year Of Joining : 2015, Salary : 11000.5, Id : 199, Name : Amelia Zoe, age : 24, Gender : Female, Department : Sales And Marketing, Year Of Joining : 2016, Salary : 11500.0, Id : 255, Name : Ali Baig, age : 23, Gender : Male, Department : Infrastructure, Year Of Joining : 2018, Salary : 12700.0, Id : 122, Name : Paul Niksui, age : 25, Gender : Male, Department : Sales And Marketing, Year Of Joining : 2015, Salary : 13500.0, Id : 211, Name : Jasna Kaur, age : 27, Gender : Female, Department : Infrastructure, Year Of Joining : 2014, Salary : 15700.0, Id : 133, Name : Martin Theron, age : 29, Gender : Male, Department : Infrastructure, Year Of Joining : 2012, Salary : 18000.0, Id : 233, Name : Jyothi Reddy, age : 27, Gender : Female, Department : Account And Finance, Year Of Joining : 2013, Salary : 21300.0, Id : 155, Name : Nima Roy, age : 27, Gender : Female, Department : HR, Year Of Joining : 2013, Salary : 22700.0, Id : 111, Name : Jiya Brein, age : 32, Gender : Female, Department : HR, Year Of Joining : 2011, Salary : 25000.0, Id : 177, Name : Manu Sharma, age : 35, Gender : Male, Department : Account And Finance, Year Of Joining : 2010, Salary : 27000.0, Id : 222, Name : Nitin Joshi, age : 25, Gender : Male, Department : Product Development, Year Of Joining : 2016, Salary : 28200.0, Id : 266, Name : Sanvi Pandey, age : 26, Gender : Female, Department : Product Development, Year Of Joining : 2015, Salary : 28900.0, Id : 144, Name : Murali Gowda, age : 28, Gender : Male, Department : Product Development, Year Of Joining : 2014, Salary : 32500.0, Id : 188, Name : Wang Liu, age : 31, Gender : Male, Department : Product Development, Year Of Joining : 2015, Salary : 34500.0, Id : 277, Name : Anuj Chettiar, age : 31, Gender : Male, Department : Product Development, Year Of Joining : 2012, Salary : 35700.0]
- Get me employee name with max salary in each department
Map<String, String> employeeNameByMaxSalaryPerDept = employees.stream() .collect(Collectors.groupingBy(Employee::getDepartment, Collectors.maxBy(Comparator.comparingDouble(Employee::getSalary)))) .entrySet().stream() .filter(entry -> entry.getValue().isPresent() == true) .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().get().name)); System.out.println(employeeNameByMaxSalaryPerDept);
{Product Development=Anuj Chettiar, Security And Transport=Jaden Dough, Sales And Marketing=Paul Niksui, Infrastructure=Martin Theron, HR=Jiya Brein, Account And Finance=Manu Sharma}
- Find average salary in each department.
Map<String, Double> averageSalaryInEachDept = employees.stream() .collect(Collectors.groupingBy(Employee::getDepartment, Collectors.averagingDouble(Employee::getSalary))); System.out.println(averageSalaryInEachDept);
{Product Development=31960.0, Security And Transport=10750.25, Sales And Marketing=11900.166666666666, Infrastructure=15466.666666666666, HR=23850.0, Account And Finance=24150.0}
- Find the employees whose department is Product Development and sort them by their experience level, with the most experienced people listed first.
List<Employee> productDevelopmentEmployeeWithExperiance = employees.stream() .filter(employee -> employee.getDepartment()=="Product Development") .sorted(Comparator.comparingInt(Employee::getYearOfJoining)) .collect(Collectors.toList()); System.out.println(productDevelopmentEmployeeWithExperiance);
[Id : 277, Name : Anuj Chettiar, age : 31, Gender : Male, Department : Product Development, Year Of Joining : 2012, Salary : 35700.0, Id : 144, Name : Murali Gowda, age : 28, Gender : Male, Department : Product Development, Year Of Joining : 2014, Salary : 32500.0, Id : 188, Name : Wang Liu, age : 31, Gender : Male, Department : Product Development, Year Of Joining : 2015, Salary : 34500.0, Id : 266, Name : Sanvi Pandey, age : 26, Gender : Female, Department : Product Development, Year Of Joining : 2015, Salary : 28900.0, Id : 222, Name : Nitin Joshi, age : 25, Gender : Male, Department : Product Development, Year Of Joining : 2016, Salary : 28200.0]
- Find the department which has maximum number of employee.
Map.Entry<String, Long> deptWithMaxEmployee = employees.stream() .collect(Collectors.groupingBy(Employee::getDepartment, Collectors.counting())) .entrySet().stream() .max(Map.Entry.comparingByValue()) // or .max((e1, e2) -> Long.compare(e1.getValue(), e2.getValue())) .get(); System.out.println(deptWithMaxEmployee);
Product Development=5
- Find the average age of male and female employee
Map<String, Double> avgGenderAge= employees.stream() .collect(Collectors.groupingBy(Employee::getGender, Collectors.averagingInt(Employee::getAge))); System.out.println(avgGenderAge);
{Male=30.181818181818183, Female=27.166666666666668}
- Find the employee who joined the company between 2011 to 2015.
List<Employee> empBtwYear = employees.stream() .filter(employee -> employee.yearOfJoining>=2011 && employee.yearOfJoining <=2015) .collect(Collectors.toList()); System.out.println(empBtwYear);
[Id : 111, Name : Jiya Brein, age : 32, Gender : Female, Department : HR, Year Of Joining : 2011, Salary : 25000.0, Id : 122, Name : Paul Niksui, age : 25, Gender : Male, Department : Sales And Marketing, Year Of Joining : 2015, Salary : 13500.0, Id : 133, Name : Martin Theron, age : 29, Gender : Male, Department : Infrastructure, Year Of Joining : 2012, Salary : 18000.0, Id : 144, Name : Murali Gowda, age : 28, Gender : Male, Department : Product Development, Year Of Joining : 2014, Salary : 32500.0, Id : 155, Name : Nima Roy, age : 27, Gender : Female, Department : HR, Year Of Joining : 2013, Salary : 22700.0, Id : 188, Name : Wang Liu, age : 31, Gender : Male, Department : Product Development, Year Of Joining : 2015, Salary : 34500.0, Id : 200, Name : Jaden Dough, age : 38, Gender : Male, Department : Security And Transport, Year Of Joining : 2015, Salary : 11000.5, Id : 211, Name : Jasna Kaur, age : 27, Gender : Female, Department : Infrastructure, Year Of Joining : 2014, Salary : 15700.0, Id : 233, Name : Jyothi Reddy, age : 27, Gender : Female, Department : Account And Finance, Year Of Joining : 2013, Salary : 21300.0, Id : 266, Name : Sanvi Pandey, age : 26, Gender : Female, Department : Product Development, Year Of Joining : 2015, Salary : 28900.0, Id : 277, Name : Anuj Chettiar, age : 31, Gender : Male, Department : Product Development, Year Of Joining : 2012, Salary : 35700.0]
For part II of stream api, click here