Java >> Java tutorial >  >> Tag >> boolean

Java Stream:opdel i to lister efter boolesk prædikat

Collectors.partitioningBy :

Map<Boolean, List<Employee>> partitioned = 
    listOfEmployees.stream().collect(
        Collectors.partitioningBy(Employee::isActive));

Det resulterende kort indeholder to lister, svarende til om prædikatet blev matchet eller ej:

List<Employee> activeEmployees = partitioned.get(true);
List<Employee> formerEmployees = partitioned.get(false);

Der er et par grunde til at bruge partitioningBy over groupingBy (som foreslået af Juan Carlos Mendoza):

For det første parameteren groupingBy er en Function<Employee, Boolean> (i dette tilfælde), og så er der mulighed for at give den en funktion, der kan returnere null, , hvilket betyder, at der ville være en 3. partition, hvis den funktion returnerer null for nogen af ​​medarbejderne. partitioningBy bruger en Predicate<Employee> , så den kan kun returnere 2 partitioner. hvilket ville resultere i en NullPointerException bliver smidt af indsamleren:Selvom det ikke er dokumenteret eksplicit, er der eksplicit kastet en undtagelse for null-nøgler, formentlig på grund af adfærden hos Map.computeIfAbsent at "Hvis funktionen returnerer null, registreres ingen mapping", hvilket betyder, at elementer ellers ville blive droppet lydløst fra outputtet. (Tak til lczapski for at påpege dette).

For det andet får du to lister (*) i det resulterende kort med partitioningBy; med groupingBy , får du kun nøgle/værdi-par, hvor elementer er knyttet til den givne nøgle:

System.out.println(
    Stream.empty().collect(Collectors.partitioningBy(a -> false)));
// Output: {false=[], true=[]}

System.out.println(
    Stream.empty().collect(Collectors.groupingBy(a -> false)));
// Output: {}

(*) Denne adfærd er ikke dokumenteret i Java 8 Javadoc, men den blev tilføjet til Java 9.


Du kan også bruge groupingBy i dette tilfælde, da der er 2 gruppemuligheder (aktive og inaktive medarbejdere):

Map<Boolean, List<Employee>> grouped = employees.stream()
                .collect(Collectors.groupingBy(Employee::isActive));

List<Employee> activeEmployees = grouped.get(true);
List<Employee> formerEmployees = grouped.get(false);

Hvis du er åben for at bruge et tredjepartsbibliotek, vil dette fungere med Collectors2.partition fra Eclipse Collections.

PartitionMutableList<Employee> partition =
        employees.stream().collect(
                Collectors2.partition(Employee::isActive, PartitionFastList::new));

List<Employee> activeEmployees = partition.getSelected();
List<Employee> formerEmployees = partition.getRejected();

Du kan også forenkle tingene ved at bruge ListIterate .

PartitionMutableList<Employee> partition =
        ListIterate.partition(employees, Employee::isActive);

List<Employee> activeEmployees = partition.getSelected();
List<Employee> formerEmployees = partition.getRejected();

PartitionMutableList er en type, der strækker sig fra PartitionIterable . Hver undertype af PartitionIterable har en samling for positive resultater getSelected() og negative resultater getRejected() .

Bemærk:Jeg er en forpligter til Eclipse Collections.


Java tag