I have a use case where I have all the Employee data in a list (List<Employee> employeesList
) and I would like to get the required employees by providing another list of employee ID's (List<String> employeeIdList
) I need the same order of employeeIdList
for the employees after retrieval.
I am able to achieve this with the regular nested for loop, but I would like to check what's the best way to achieve it using Java streams.
By using the regular streams, I am not getting the right order, so I tried to check a condition during the iteration and added to a different list, but I still have to collect the objects which I am really not using them anywhere.
Is there any other best option to achieve this functionality. Any help is appreciated.
Below is the sample code.
package com.test;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
/**
* The Class SimpleClass.
*/
public class SimpleClass {
/**
* The main method.
*
* @param args the arguments
*/
public static void main(String[] args) {
Employee employee1 = new Employee("1", "Employee 1");
Employee employee2 = new Employee("2", "Employee 2");
Employee employee3 = new Employee("3", "Employee 3");
Employee employee4 = new Employee("4", "Employee 4");
Employee employee5 = new Employee("5", "Employee 5");
List<Employee> employeesList = new LinkedList<>();
employeesList.add(employee5);
employeesList.add(employee1);
employeesList.add(employee2);
employeesList.add(employee3);
employeesList.add(employee4);
List<String> neededEmployees = new LinkedList<>();
neededEmployees.add("4");
neededEmployees.add("1");
neededEmployees.add("5");
/* Nested For Loop */
List<Employee> requiredEmployeesList = new LinkedList<>();
for (String employeeId : neededEmployees) {
for (Employee employee : employeesList) {
if (employee.getId().equals(employeeId)) {
requiredEmployeesList.add(employee);
}
}
}
printEmployeeDetails(requiredEmployeesList);
/* Using Streams - Not returning the required order */
List<Employee> employeesListNew = employeesList.stream().filter(
employee -> neededEmployees.stream().anyMatch(employeeId -> employeeId.equals(employee.getId())))
.collect(Collectors.toList());
printEmployeeDetails(employeesListNew);
/* Using Streams - adding to a different list based on condition - This provides the right order as required*/
List<Employee> sortedEmployeesList = new ArrayList<>();
neededEmployees.stream()
.filter(employeeId -> employeesList.stream()
.anyMatch(employee -> employee.getId().equals(employeeId) ? sortedEmployeesList.add(employee) : false))
.collect(Collectors.toList());
printEmployeeDetails(sortedEmployeesList);
}
/**
* Prints the employee details.
*
* @param employeesList the employees list
*/
private static void printEmployeeDetails(List<Employee> employeesList) {
System.out.println("Printing Employees List");
for (Employee employee : employeesList) {
System.out.println(employee.getId());
System.out.println(employee.getName());
}
}
}
class Employee {
String id;
String name;
// Setter, Getter and AllArgsConstructor
}
One of the ways to do what you're looking for without sorting the actual data would be using a map of id to an employee itself such as:
Map<String, Employee> employeeMap = employeesList.stream()
.collect(Collectors.toMap(Employee::getId, Function.identity()));
and then mapping them iterating in the order based on the neededEmployees
as follows:
List<Employee> requiredAndSortedEmployeesList = neededEmployees.stream()
.map(employeeMap::get)
.collect(Collectors.toList());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With