Ottieni dipendenti prima e dopo la data specifica di iscrizione dall'elenco dei dipendenti con flusso Java


9

Ho Listdelle Employees con date di iscrizione diverse. Voglio ottenere dipendenti prima e dopo la data specifica di iscrizione dalla lista usando i flussi.

ho provato a seguire il codice,

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

C'è un modo per farlo in un singolo flusso?


1
È possibile utilizzarepartitioningBy
Code_Mode

5
Prima e dopo - quindi vuoi tutti i dipendenti tranne quelli che si sono uniti alla data?
John 3136,

Supponendo che "sia stato un dipendente almeno da", ti consigliamo di dividerlo prima e non prima, senza preoccuparti affatto.
JollyJoker il

Risposte:


16

Puoi usare partitioningBycome di seguito,

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 Restituisce un Collector che suddivide gli elementi di input in base a un Predicato e li organizza in aMap<Boolean, List<T>>

Si noti che questo non gestirà i dipendenti con specificDate.


1
Una spiegazione del codice sarà eccezionale.
Vishwa Ratna,

2
Questo non fa esattamente ciò che fa il codice in questione - i dipendenti con specificDateatterreranno in falsepartizione, dove non si trova il codice in questione in nessuno
Andronicus

In che modo l'aggiunta specificDate.plusDays(1)risolve il problema? specificDatesarà ancora nella falseparte.
Andronico

Quindi sarà nella truepartizione ...
Andronico

1
@Andronicus: solo OP sa se questo comportamento è un bug o una funzionalità. A me sembra più sicuro non escludere alcun dipendente.
Eric Duminil,

9

Se il tuo elenco può contenere voci unite alspecificDate , potresti trovare groupingByutile:

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

La resultmappa contiene Employeerecord raggruppati per posizione relativamente a specificDate, quindi puoi scegliere chi si è unito prima, dopo o alla data specificata.


Questa dovrebbe essere la risposta accettata
Andronico

2
-1. Stai compareToassumendo il falso presupposto che restituirà solo -1, 0 o 1. In realtà LocalDate.compare Per restituire qualsiasi int.
MikeFHay,

1
@MikeFHay Grazie per averlo sottolineato. Ho fatto un test molto veloce e sono saltato alle conclusioni. Implementazione modificata (e improvvisamente sembra complessa).
ernest_k,

2
@ernest_k: è possibile utilizzare l'originale compareToe chiamarlo Integer.signum.
Eric Duminil,

1
@JollyJoker Nel caso in cui non lo sapessi, puoi collegarti a una linea specifica in github: in questo modo . Facendo clic sul numero di riga si modifica direttamente l'URL. Sentiti libero di ignorare se lo sapevi già o non ti interessa. ;)
Eric Duminil il

4

Devi filtrare i dipendenti con questa data particolare. Quindi è possibile utilizzare il partizionamento:

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

Ciò creerà una mappa delle raccolte in base al soddisfacimento del predicato.


Imparato partitioningBy oggi
Vishwa Ratna,

No, non puoi filtrare con la data poiché
filtrerebbe i

@Code_Mode oh, sì, mi sono perso, grazie!
Andronico

2

È possibile utilizzare Collectors.groupingBye utilizzare il compareTometodo per raggruppare l'elenco dei dipendenti in base alla data precedente, corrente e futura

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

Quindi l'output sarà

key--> -1 ---> will have employees with previous date
key--> 0 ---> will have employees with current date
key--> 1 ---> will have employees with future date
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.