Получить сотрудников до и после определенной даты присоединения из списка сотрудников с потоком Java


9

Я имею Listв Employeeс с различными датами присоединения. Я хочу получить сотрудников до и после определенной даты присоединения из списка с помощью потоков.

я попробовал следующий код,

 List<Employee> employeeListAfter = employeeList.stream()
                .filter(e -> e.joiningDate.isAfter(specificDate))
                .collect(Collectors.toList());

List<Employee> employeeListBefore = employeeList.stream()
        .filter(e -> e.joiningDate.isBefore(specificDate))
        .collect(Collectors.toList());

class Employee{
    int id;
    String name;
    LocalDate joiningDate;
}

Есть ли способ сделать это в одном потоке?


1
Вы можете использоватьpartitioningBy
Code_Mode

5
До и после - значит, вы хотите, чтобы все сотрудники, кроме тех, кто присоединился к дате?
John3136

Предполагая, что он «был сотрудником, по крайней мере, с тех пор», вы захотите разделиться на до и не раньше, не заботясь об этом вообще.
JollyJoker

Ответы:


16

Вы можете использовать partitioningByкак ниже,

Map<Boolean, List<Employee>> listMap = employeeList.stream()
        .collect(Collectors.partitioningBy(e -> e.joiningDate.isAfter(specificDate)));

List<Employee> employeeListAfter = listMap.get(true);
List<Employee> employeeListBefore = listMap.get(false);

partitioningBy Возвращает Collector, который разделяет входные элементы в соответствии с предикатом и организует их вMap<Boolean, List<T>>

Обратите внимание, что это не будет работать с сотрудниками specificDate.


1
Объяснение кода будет отличным.
Вишва Ратна

2
Это не делает в точности то, что делает рассматриваемый код - сотрудники с specificDateтем false, что они попадают в раздел, тогда как в соответствующем коде нет
Andronicus

Как добавление specificDate.plusDays(1)решает проблему? specificDateвсе еще будет в falseчасти.
Андроник

Тогда это будет в trueразделе ...
Андроник

1
@Andronicus: Только ОП знает, является ли это поведение ошибкой или функцией. Мне кажется, безопаснее не оставлять ни одного сотрудника.
Эрик Думинил

9

Если в вашем списке могут быть записи , присоединившиеся кspecificDate , то вам может groupingByпригодиться:

Map<Integer, List<Employee>> result = employeeList.stream()
    .map(emp -> new AbstractMap.SimpleEntry<>(specificDate.compareTo(emp.getJoiningDate()), emp))
    .collect(Collectors.groupingBy(entry -> entry.getKey() > 0 ? 1 : (entry.getKey() < 0 ? -1 : 0),
            Collectors.mapping(entry -> entry.getValue(), Collectors.toList())));

employeeListAfter = result.get(-1);
employeeListBefore = result.get(1);
employeeListOnSpecificDate = result.get(0);

resultКарта содержит Employeeзаписи , сгруппированные по положению относительно specificDate, так что вы можете выбрать , кто присоединился к до, после или на указанную дату.


Это должен быть принятый ответ
Андроник

2
-1. Вы делаете ложное предположение, что compareToвернет только -1, 0 или 1. На самом деле LocalDate.compareTo может вернуть любое значение типа int.
MikeFHay

1
@MikeFHay Спасибо за указание на это. Я сделал очень быстрый тест и сделал поспешные выводы. Изменена реализация (и вдруг это выглядит сложно).
ernest_k

2
@ernest_k: Вы можете использовать оригинал compareToи позвонить Integer.signumпо нему.
Эрик Думинил

1
@JollyJoker На всякий случай, если вы не знали, вы можете добавить ссылку на определенную строку в github: вот так . Нажатие на номер строки изменяет URL-адрес напрямую. Не стесняйтесь игнорировать, если вы уже знали или не волнует. ;)
Эрик Думинил

4

Вы должны отфильтровать сотрудников с этой конкретной датой. Тогда вы можете использовать разбиение:

Map<Boolean, List<Employee>> partitioned = employeeList.stream()
    .filter(e -> !e.joiningDate.equals(specificDate))
    .collect(partitioningBy(e -> e.joiningDate.isAfter(specificDate)));

List<Employee> employeeListAfter = partitioned.get(true);
List<Employee> employeeListBefore = partitioned.get(false);

Это создаст карту коллекций на основе того, соответствуют ли они предикату.


Узнал partitioningBy сегодня.
Вишва Ратна

Нет, вы не можете фильтровать по дате, так как это отфильтровывает сотрудников только с specificDate
Code_Mode

@Code_Mode о, да, я пропустил это, спасибо!
Андроник

2

Вы можете использовать Collectors.groupingByи использовать compareToметод для группировки списка сотрудников на основе предыдущей, текущей и будущей даты

Map<Integer, List<Employee>> result = employeeList.stream()
            .collect(Collectors.groupingBy(e-> e.joiningDate.compareTo(specificDate)< 0 ? -1 : (e.joiningDate.compareTo(specificDate) == 0 ? 0 : 1)));

Таким образом, выход будет

key--> -1 ---> will have employees with previous date
key--> 0 ---> will have employees with current date
key--> 1 ---> will have employees with future date
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.