Java Stream:按布尔谓词划分为两个列表

时间:2017-10-26 15:15:44

标签: java collections functional-programming java-stream reduce

我有employees的列表。他们有isActive布尔字段。我想将employees分为两个列表:activeEmployeesformerEmployees。是否可以使用Stream API?什么是最复杂的方式?

4 个答案:

答案 0 :(得分:14)

Collectors.partitioningBy

<DeferredInput value={..} onBlur={..}/>

生成的映射包含两个列表,对应于谓词是否匹配:

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

使用List<Employee> activeEmployees = partitioned.get(true); List<Employee> formerEmployees = partitioned.get(false); 而不是partitioningByJuan Carlos Mendoza建议),有几个原因:

首先,groupingBy的参数是groupingBy(在这种情况下),因此有可能传递一个可以返回null的函数,这意味着如果有{3}分区该函数为任何员工返回null。 Function<Employee, Boolean>使用partitioningBy,因此它只能返回2个分区。

其次,在Predicate<Employee>生成的地图中得到两个列表(*);使用partitioningBy,您只能获得元素映射到给定键的键/值对:

groupingBy

(*)Java 8 Javadoc中未记录此行为,但已为Java 9添加了此行为。

答案 1 :(得分:2)

在这种情况下您也可以使用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);

答案 2 :(得分:2)

如果您愿意使用第三方库,则可以使用Collectors2.partition中的Eclipse Collections

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

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

您还可以使用ListIterate简化操作。

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

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

PartitionMutableList是从PartitionIterable扩展的类型。 PartitionIterable的每个子类型都有一个集合,分别包含肯定结果getSelected()和否定结果getRejected()

注意:我是Eclipse Collections的提交者。

答案 3 :(得分:1)

  

最复杂的方法是什么?

Java 12当然带有新的Collectors::teeing

List<List<Emploee>> divided = employees.stream().collect(
      Collectors.teeing(
              Collectors.filtering(Emploee::isActive, Collectors.toList()),
              Collectors.filtering(Predicate.not(Emploee::isActive), Collectors.toList()),
              List::of
      ));

System.out.println(divided.get(0));  //active
System.out.println(divided.get(1));  //inactive