Collectors.partitioningBy
:
Map<Boolean, List<Employee>> partitioned =
listOfEmployees.stream().collect(
Collectors.partitioningBy(Employee::isActive));
The resulting map contains two lists, corresponding to whether or not the predicate was matched:
List<Employee> activeEmployees = partitioned.get(true);
List<Employee> formerEmployees = partitioned.get(false);
There are a couple of reasons to use partitioningBy
over groupingBy
(as suggested by Juan Carlos Mendoza):
Firstly, the parameter of groupingBy
is a Function<Employee, Boolean>
(in this case), and so there is a possibility of passing it a function which can return null, meaning there would be a 3rd partition if that function returns null for any of the employees. partitioningBy
uses a Predicate<Employee>
, so it can only ever return 2 partitions. which would result in a NullPointerException
being thrown by the collector: whilst not documented explicitly, an exception is explicitly thrown for null keys, presumably because of the behavior of Map.computeIfAbsent
that "If the function returns null no mapping is recorded", meaning elements would otherwise be dropped silently from the output. (Thanks to lczapski for pointing this out).
Secondly, you get two lists (*) in the resulting map with partitioningBy
; with groupingBy
, you only get key/value pairs where elements map to the given key:
System.out.println(
Stream.empty().collect(Collectors.partitioningBy(a -> false)));
// Output: {false=[], true=[]}
System.out.println(
Stream.empty().collect(Collectors.groupingBy(a -> false)));
// Output: {}
(*) This behavior isn't documented in the Java 8 Javadoc, but it was added for Java 9.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…