Obtenir des employés avant et après la date précise d'adhésion à partir de la liste des employés avec le flux Java

9

J'ai Listdes Employees avec différentes dates d'adhésion. Je souhaite obtenir des employés avant et après une date précise d'adhésion à partir de la liste à l'aide de flux.

j'ai essayé de suivre le 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;
}

Existe-t-il un moyen de le faire en un seul flux?

Rajiv
la source
1
Vous pouvez utiliserpartitioningBy
Code_Mode
5
Avant et après - vous voulez donc tous les employés sauf ceux qui se sont joints à la date?
John3136
En supposant que "ça a été un employé au moins depuis", vous voudrez vous séparer avant et non avant, ne pas vous soucier du tout.
JollyJoker

Réponses:

16

Vous pouvez utiliser partitioningBycomme ci-dessous,

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 Renvoie un collecteur qui partitionne les éléments d'entrée en fonction d'un prédicat et les organise en unMap<Boolean, List<T>>

Notez que cela ne gérera pas les employés avec specificDate.

Code_Mode
la source
1
Une explication du code sera géniale.
Vishwa Ratna
2
Cela ne fait pas exactement ce que fait le code en question - les employés avec specificDateatterriront en falsepartition, alors que dans le code en question aucun
Andronicus
Comment l'ajout specificDate.plusDays(1)résout-il le problème? specificDatesera toujours dans la falsepartie.
Andronicus
Ensuite, ce sera dans la truepartition ...
Andronicus
1
@Andronicus: Seul OP sait si ce comportement est un bogue ou une fonctionnalité. Pour moi, il semble plus sûr de ne laisser aucun employé de côté.
Eric Duminil
9

Si votre liste peut contenir des entrées qui se sont jointes à laspecificDate , vous pouvez trouver 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 resultcarte contient des Employeeenregistrements regroupés par position par rapport à specificDate, de sorte que vous pouvez choisir qui s'est joint avant, après ou à la date spécifiée.

ernest_k
la source
Cela devrait être la réponse acceptée
Andronicus
2
-1. Vous faites la fausse hypothèse qui compareTone renverra que -1, 0 ou 1. En fait, LocalDate.compareTo peut renvoyer n'importe quel entier.
MikeFHay
1
@MikeFHay Merci de l'avoir signalé. J'ai fait un test très rapide et sauté aux conclusions. Implémentation modifiée (et soudain, cela semble complexe).
ernest_k
2
@ernest_k: Vous pouvez utiliser l'original compareToet y faire appel Integer.signum.
Eric Duminil
1
@JollyJoker Juste au cas où vous ne le sauriez pas, vous pouvez créer un lien vers une ligne spécifique dans github: comme ceci . Un clic sur le numéro de ligne modifie directement l'URL. N'hésitez pas à ignorer si vous le saviez déjà ou si vous ne vous en souciez pas. ;)
Eric Duminil
4

Vous devez filtrer les employés avec cette date particulière. Ensuite, vous pouvez utiliser le partitionnement:

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

Cela créera une carte des collections en fonction de si elles remplissent le prédicat.

Andronicus
la source
Appris partitioningBy aujourd'hui.
Vishwa Ratna
Non, vous ne pouvez pas filtrer avec la date car cela filtrerait les employés avec seulement specificDate
Code_Mode
@Code_Mode oh, oui, ça m'a manqué, merci!
Andronicus
2

Vous pouvez utiliser Collectors.groupingByet utiliser la compareTométhode pour regrouper la liste des employés en fonction de la date précédente, actuelle et future

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

Ainsi, la sortie sera

key--> -1 ---> will have employees with previous date
key--> 0 ---> will have employees with current date
key--> 1 ---> will have employees with future date
Dead Pool
la source