Отримайте співробітників до та після конкретної дати приєднання зі списку працівників з потоку 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 Повертає колектор, який розділяє вхідні елементи згідно з предикатом і впорядковує їх уMap<Boolean, List<T>>

Зауважте, що це не впорається із працівниками specificDate.


1
Пояснення коду буде чудовим.
Vishwa Ratna

2
Це не зовсім точно, що робить код, про який йдеться - працівники, specificDateякі висаджуються на falseперегородку, де у вказаному коді немає
Андронік

Як додавання 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 сьогодні.
Вішва Ратна

Ні, ви не можете фільтрувати за датою, як це фільтрувало б працівників лише з певним
датом

@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.