Получить сотрудников до и после определенной даты присоединения из списка сотрудников с потоком 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.

Code_Mode
источник
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, так что вы можете выбрать , кто присоединился к до, после или на указанную дату.

ernest_k
источник
Это должен быть принятый ответ
Андроник
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
Тотализатор, где делаются ставки на смерть знаменитостей
источник