Holen Sie sich Mitarbeiter vor und nach einem bestimmten Beitrittsdatum aus der Liste der Mitarbeiter mit Java-Stream


9

Ich habe Listvon Employees mit unterschiedlichen Beitrittsdaten. Ich möchte Mitarbeiter vor und nach einem bestimmten Beitrittsdatum von der Liste mithilfe von Streams abrufen.

Ich habe versucht, folgenden Code,

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

Gibt es eine Möglichkeit, dies in einem einzigen Stream zu tun?


1
Sie könnenpartitioningBy
Code_Mode

5
Vorher und nachher - also möchten Sie alle Mitarbeiter außer denen, die am Datum beigetreten sind?
John3136

Angenommen, es ist "mindestens seitdem ein Mitarbeiter", möchten Sie sich in vorher und nicht vorher aufteilen und sich überhaupt nicht darum kümmern.
JollyJoker

Antworten:


16

Sie können partitioningBywie folgt verwenden:

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 Gibt einen Collector zurück, der die Eingabeelemente nach einem Prädikat partitioniert und in a organisiertMap<Boolean, List<T>>

Beachten Sie, dass dies keine Mitarbeiter mit behandelt specificDate.


1
Eine Erklärung des Codes wird großartig sein.
Vishwa Ratna

2
Dies macht nicht genau das, was der fragliche Code tut - Mitarbeiter mit specificDatelanden in der falsePartition, wo im fraglichen Code keine
Andronicus

Wie wird specificDate.plusDays(1)das Problem durch Hinzufügen behoben? specificDatewird noch in dem falseTeil sein.
Andronicus

Dann wird es in der truePartition sein ...
Andronicus

1
@Andronicus: Nur OP weiß, ob dieses Verhalten ein Fehler oder eine Funktion ist. Mir scheint es sicherer, keinen Mitarbeiter auszulassen.
Eric Duminil

9

Wenn Ihre Liste Einträge enthalten kann, die dem beigetreten sindspecificDate , finden Sie möglicherweise Folgendes groupingBynützlich:

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

Die resultKarte enthält EmployeeDatensätze, die nach Position relativ zu gruppiert sind specificDate, sodass Sie auswählen können, wer vor, nach oder am angegebenen Datum beigetreten ist.


Dies sollte die akzeptierte Antwort sein
Andronicus

2
-1. Sie gehen von der falschen Annahme aus, dass compareTonur -1, 0 oder 1 zurückgegeben wird. Tatsächlich kann LocalDate.compareTo jedes int zurückgeben.
MikeFHay

1
@ MikeFHay Danke, dass du darauf hingewiesen hast. Ich machte einen sehr schnellen Test und kam zu Schlussfolgerungen. Geänderte Implementierung (und plötzlich sieht es komplex aus).
ernest_k

2
@ernest_k: Sie könnten das Original verwenden compareTound es aufrufen Integer.signum.
Eric Duminil

1
@JollyJoker Nur für den Fall, dass Sie es nicht wussten, können Sie in github auf eine bestimmte Zeile verlinken: so . Durch Klicken auf die Zeilennummer wird die URL direkt geändert. Fühlen Sie sich frei zu ignorieren, wenn Sie es bereits wussten oder sich nicht darum kümmern. ;)
Eric Duminil

4

Sie müssen Mitarbeiter mit diesem bestimmten Datum herausfiltern. Dann können Sie die Partitionierung verwenden:

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

Dadurch wird eine Karte mit Sammlungen erstellt, die darauf basiert, ob sie das Prädikat erfüllen.


partitioningBy Heute gelernt .
Vishwa Ratna

Nein, Sie können nicht nach Datum filtern, da dies nur Mitarbeiter mit einem bestimmten Datum filtern würde
Code_Mode

@Code_Mode oh ja, das habe ich verpasst, danke!
Andronicus

2

Sie können mit Collectors.groupingByEinsatz und compareToauf früheren, Liste basiert Mitarbeiter Methode für die Gruppierung der aktuellen und zukünftigen Datum

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

So wird die Ausgabe sein

key--> -1 ---> will have employees with previous date
key--> 0 ---> will have employees with current date
key--> 1 ---> will have employees with future date
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.