Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need to get the second list ordering when validating the content between 2 different lists by using Java Streams

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
}
like image 270
Sudheer Donaboina Avatar asked Dec 31 '22 08:12

Sudheer Donaboina


1 Answers

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());
like image 134
Naman Avatar answered Jan 13 '23 23:01

Naman