我有一份员工
的列表。他们有 isActive
boolean 字段。我想将 employees
分成两个列表:activeEmployees
和 formerEmployees
。是否可以使用 Stream API?什么是最复杂的方法?
最佳答案
Map<Boolean, List<Employee>> partitioned =
listOfEmployees.stream().collect(
Collectors.partitioningBy(Employee::isActive));
生成的映射包含两个列表,对应于谓词是否匹配:
List<Employee> activeEmployees = partitioned.get(true);
List<Employee> formerEmployees = partitioned.get(false);
使用 partitioningBy
有几个原因在 groupingBy
(如 Juan Carlos Mendoza 所建议):
首先是groupingBy
的参数是 Function<Employee, Boolean>
(在这种情况下),因此有可能向它传递一个可以返回 null 的函数, 意味着如果该函数为任何员工返回 null,则将有第三个分区。 这将导致 partitioningBy
使用 Predicate<Employee>
,所以它只能返回 2 个分区。NullPointerException
被收集器抛出:虽然没有明确记录,但会为空键显式抛出异常,大概是因为 Map.computeIfAbsent
的行为“如果函数返回 null,则不记录任何映射”,这意味着元素将从输出中静默删除。 (感谢 lczapski 指出这一点)。
其次,您在生成的 map 中使用 partitioningBy
获得两个列表 (*) ;与 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: {}
(*) 此行为未记录在 Java 8 Javadoc 中, 但它是为 Java 9 添加的.
关于Java 流 : divide into two lists by boolean predicate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46958023/