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?


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.


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.


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.


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.