Необходимо получить второй порядок списков при проверке содержимого между двумя различными списками с помощью Java Streams - PullRequest
5 голосов
/ 15 января 2020

У меня есть сценарий использования, когда у меня есть все данные о сотрудниках в списке (List<Employee> employeesList), и я хотел бы получить требуемых сотрудников, предоставив другой список идентификаторов сотрудников (List<String> employeeIdList). Мне нужен тот же порядок employeeIdList для сотрудников после поиска.

Я могу добиться этого с помощью обычной вложенности для l oop, но я хотел бы проверить, как лучше всего добиться этого с помощью Java потоков.

Используя обычные потоки, я не получаю правильный порядок, поэтому я попытался проверить условие во время итерации и добавил в другой список, но мне все еще нужно собрать объекты, которые я на самом деле нигде не использую.

Есть ли другой лучший вариант для достижения этой функциональности. Любая помощь приветствуется.

Ниже приведен пример кода.

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
}

Ответы [ 5 ]

5 голосов
/ 16 января 2020

Один из способов сделать то, что вы ищете, без сортировки фактических данных, - это использовать карту идентификатора самого сотрудника, например:

Map<String, Employee> employeeMap = employeesList.stream()
        .collect(Collectors.toMap(Employee::getId, Function.identity()));

, а затем сопоставить их итерации в порядке на основе neededEmployees следующим образом:

List<Employee> requiredAndSortedEmployeesList = neededEmployees.stream()
        .map(employeeMap::get)
        .collect(Collectors.toList());
3 голосов
/ 16 января 2020

Вы должны использовать операции filter и sort для вашего сценария.

для сортировки вы должны реализовать пользовательский comparator на основе индекса neededEmployees элементов.

Comparator<Employee> comparator=Comparator.comparingInt(o -> neededEmployees.indexOf(o.id));

на самом деле этот компаратор действует на основе индекса employeeId в списке neededEmployees.

, а затем используйте filter, чтобы отфильтровать ваш список на основе neededEmployees после того, как он отсортирован по пользовательский компаратор. хотя эта доза компаратора не имеет хороших показателей для огромного списка, но поскольку размер списка neededEmployees невелик, на самом деле в этом случае у него нет узкого места.

та же причина для фильтра верна. Вы можете использовать Set вместо List, но здесь это не важно, поскольку его размер невелик.

sortedEmployeesList = employeesList.stream()
          .filter(employee -> neededEmployees.contains(employee.id))
          .sorted(comparator)
          .collect(Collectors.toList());

[Employee {id = '4', name = 'Employee 4'}, Employee {id = '1', name = 'Employee 1'}, Employee {id = ' 5 ', name =' Employee 5 '}]

1 голос
/ 15 января 2020

Отредактировано

Он состоит из следующих двух шагов

1-фильтр employeeList с необходимыми сотрудниками

  • возвращает список сотрудников. (List<List<Employee>)

Это означает

{{employee4}, {{employee1}}, {employee5}}


2 - использовать flatMap для выравнивания предыдущего списка

это означает

конвертировать {{employee4}, {{employee1}} , {employee5}} до {employee4, employee1, employee5}


Я кодировал вышеупомянутый сценарий следующим образом

List<Employee> result = neededEmployees.stream().
                map(neededEmployee -> employeesList.stream().
                        filter(employee -> employee.getId().equals(neededEmployee))
                        .collect(Collectors.toList()))
                .flatMap(Collection::stream)
                .collect(Collectors.toList());

Печать результатов

result.forEach(

    employee -> System.out.println(employee.getName())

);

Сотрудник 4

Сотрудник 1

Сотрудник 5

1 голос
/ 15 января 2020

ваша первая попытка потока идет в порядке сотрудника, а не в заказе сотрудника. В основном используйте первый, но переворачивайте списки, как второй, но тот создает список, а затем просто выбрасывает его. и затем добавляет его в другой список. Просто сделайте это :)

List<Employee> newList = neededEmployees.stream()
             .map(eid-> employeesList.stream().filter(employee -> 
                       employee.getId().equals(eid)).findAny().get())
            .collect(Collectors.toList());
0 голосов
/ 15 января 2020
    neededEmployees.forEach(eid->employeesList.forEach(emp->{
        if(eid.equalsIgnoreCase(emp.getId())) {
            requiredEmployeesList.add(emp);
        }
    }));

    requiredEmployeesList.forEach(re->System.out.println(re.getId()));

Попробуйте это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...