[英]Java Stream: divide into two lists by boolean predicate
I have a list of employees
.我有一份
employees
名单。 They have isActive
boolean field.他们有
isActive
布尔字段。 I would like to divide employees
into two lists: activeEmployees
and formerEmployees
.我想将
employees
分为两个列表: activeEmployees
和前formerEmployees
。 Is it possible to do using Stream API?是否可以使用 Stream API? What is the most sophisticated way?
最复杂的方法是什么?
Collectors.partitioningBy
: 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 ):使用
partitioningBy
不是groupingBy
有几个原因(如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.
首先,
groupingBy
的参数是一个Function<Employee, Boolean>
(在这种情况下),因此有可能向它传递一个可以返回 null 的函数,这
意味着如果该函数为任何
返回 null,
则将有第三个分区的员工。
partitioningBy
uses a
Predicate<Employee>
, so it can only ever return 2 partitions.
which would result in a partitioningBy
使用
Predicate<Employee>
,因此它只能返回 2 个分区。
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.这将导致收集器抛出
NullPointerException
:虽然没有明确记录,但为空键显式抛出异常,大概是因为Map.computeIfAbsent
的行为“如果函数返回 null 则不记录映射”,意思是元素否则将从输出中静默删除。 (Thanks to lczapski for pointing this out). (感谢lczapski指出这一点)。
Secondly, you get two lists (*) in the resulting map with partitioningBy
;其次,您在结果映射中使用
partitioningBy
获得两个列表 (*); with groupingBy
, you only get key/value pairs where elements map to the given key:使用
groupingBy
,您只能获得元素映射到给定键的键/值对:
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 . (*) 此行为未记录在Java 8 Javadoc 中,但已为Java 9添加。
You can also use groupingBy in this case as there are 2 group posibilities (active and inactive employees):在这种情况下,您也可以使用groupingBy ,因为有 2 个组可能性(活跃和不活跃的员工):
Map<Boolean, List<Employee>> grouped = employees.stream()
.collect(Collectors.groupingBy(Employee::isActive));
List<Employee> activeEmployees = grouped.get(true);
List<Employee> formerEmployees = grouped.get(false);
What is the most sophisticated way?
最复杂的方法是什么?
Java 12 of course with new Collectors::teeing
Java 12 当然有新的
Collectors::teeing
List<List<Employee>> divided = employees.stream().collect(
Collectors.teeing(
Collectors.filtering(Employee::isActive, Collectors.toList()),
Collectors.filtering(Predicate.not(Employee::isActive), Collectors.toList()),
List::of
));
System.out.println(divided.get(0)); //active
System.out.println(divided.get(1)); //inactive
If you are open to using a third-party library, this will work using Collectors2.partition
from Eclipse Collections .如果您愿意使用第三方库,这将使用Eclipse Collections 中的
Collectors2.partition
工作。
PartitionMutableList<Employee> partition =
employees.stream().collect(
Collectors2.partition(Employee::isActive, PartitionFastList::new));
List<Employee> activeEmployees = partition.getSelected();
List<Employee> formerEmployees = partition.getRejected();
You can also simplify things using ListIterate
.您还可以使用
ListIterate
简化事情。
PartitionMutableList<Employee> partition =
ListIterate.partition(employees, Employee::isActive);
List<Employee> activeEmployees = partition.getSelected();
List<Employee> formerEmployees = partition.getRejected();
PartitionMutableList
is a type that extends from PartitionIterable
. PartitionMutableList
是一种从PartitionIterable
扩展的类型。 Every subtype of PartitionIterable
has a collection for positive results getSelected()
and negative results getRejected()
. PartitionIterable
每个子类型都有一个用于正结果getSelected()
和负结果getRejected()
的集合。
Note: I am a committer for Eclipse Collections.注意:我是 Eclipse Collections 的提交者。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.