Uzyskaj pracowników przed i po określonej dacie dołączenia z listy pracowników ze strumieniem Java

9

Mam Listz Employees z różnymi datami łączenia. Chcę uzyskać pracowników przed określoną datą dołączenia z listy i po niej za pomocą strumieni.

próbowałem śledzić kod,

 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;
}

Czy można to zrobić w jednym strumieniu?

Rajiv
źródło
1
Możesz użyćpartitioningBy
Code_Mode
5
Przed i po - więc chcesz wszystkich pracowników oprócz tych, którzy dołączyli w tym dniu?
John3136
Zakładając, że „był przynajmniej pracownikiem od tego czasu”, będziesz chciał podzielić się przed, a nie wcześniej, wcale się tym nie przejmując.
JollyJoker

Odpowiedzi:

16

Możesz użyć partitioningByjak poniżej,

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 Zwraca moduł zbierający, który dzieli elementy wejściowe zgodnie z predykatem i organizuje je wMap<Boolean, List<T>>

Pamiętaj, że nie będzie to obsługiwać pracowników specificDate.

Code_Mode
źródło
1
Wyjaśnienie kodu będzie świetne.
Vishwa Ratna
2
Nie robi to dokładnie tego, co robi dany kod - pracownicy specificDate, którzy wylądują w falsepartycji, gdzie nie ma żadnego kodu
Andronicus
Jak dodanie specificDate.plusDays(1)rozwiązuje problem? specificDatenadal będzie w tej falseczęści.
Andronicus
Wtedy będzie w truepartycji ...
Andronicus
1
@Andronicus: Tylko OP wie, czy to zachowanie jest błędem czy cechą. Wydaje mi się, że bezpieczniej jest nie pozostawiać żadnego pracownika.
Eric Duminil
9

Jeśli twoja lista może zawierać wpisy, które dołączyłyspecificDate , być może groupingByprzydatne:

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);

resultUlicami zawiera Employeezapisy pogrupowane według położenia względem specificDate, więc można wybrać, który dołączył przed, po lub w określonym dniu.

ernest_k
źródło
To powinna być zaakceptowana odpowiedź
Andronicus
2
-1. Podejmujesz fałszywe założenie, które compareTozwróci tylko -1, 0 lub 1. W rzeczywistości LocalDate.compareTo może zwrócić dowolną liczbę całkowitą.
MikeFHay
1
@MikeFHay Dzięki za zwrócenie na to uwagi. Zrobiłem bardzo szybki test i doszedłem do wniosków. Zmieniono implementację (i nagle wygląda na skomplikowaną).
ernest_k
2
@ernest_k: Możesz użyć oryginału compareToi wywołać Integer.signumgo.
Eric Duminil
1
@JollyJoker Na wypadek, gdybyś nie wiedział, możesz utworzyć link do określonej linii w github: w ten sposób . Kliknięcie numeru linii zmienia adres URL bezpośrednio. Możesz zignorować, jeśli już wiesz, czy cię to nie obchodzi. ;)
Eric Duminil
4

Musisz odfiltrować pracowników z tą konkretną datą. Następnie możesz użyć partycjonowania:

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);

Spowoduje to utworzenie mapy kolekcji na podstawie tego, czy spełniają one predykat.

Andronikus
źródło
Nauczyłem się partitioningBy dzisiaj.
Vishwa Ratna
Nie, nie można filtrować według daty, ponieważ filtrowałby pracowników tylko z określoną
datą
@Code_Mode och, tak, tęskniłem za tym, dziękuję!
Andronicus
2

Możesz użyć Collectors.groupingByi użyć compareTometody grupowania listy pracowników na podstawie poprzedniej, bieżącej i przyszłej daty

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

Więc wynik będzie

key--> -1 ---> will have employees with previous date
key--> 0 ---> will have employees with current date
key--> 1 ---> will have employees with future date
Deadpool
źródło