如何根据对象的布尔值过滤流

How to filter a stream based on the boolean of an object

我有一个对象(汽车)列表,我想将所有工作的汽车放在列表的第一位,然后是非工作的汽车。

汽车对象有一个 isWorking() getter 等于 truefalse.

cars.stream()
    .filter(x->x.isWorking())
    .collect(Collectors.toList());
System.out.println("Working Cars First" + car);

使用 Stream API 收集器执行 grouping 到地图 Map<Boolean, List<Car>> 并将所有列表连续添加到新列表中,从而产生“工作”汽车首先出现。或者更好的是,使用 partitioning,它与分组相同,但基于布尔键,由于给定的 Predicate 而导致具有两个条目的映射。这是一些代码:

List<Car> cars = ...
Map<Boolean, List<Car>> resultMap = cars.stream()
            .collect(Collectors.partitioningBy(Car::isWorking));

List<Car> orderedCars = new ArrayList<>();
orderedCars.addAll(resultMap.get(true));
orderedCars.addAll(resultMap.get(false));

... 或使用 collectingAndThen 收集器的单个语句:

List<Car> orderedCars = cars.stream()
    .collect(
        Collectors.collectingAndThen(
            Collectors.partitioningBy(Car::isWorking),
            map -> Stream.of(map.get(true), map.get(false))
                         .flatMap(List::stream)
                         .collect(Collectors.toList())));

这个解决方案在时间复杂度上优于排序,因为分区收集器应该在线性时间内处理列表,但是,我们需要在内存中存储更多对象,这可能不适合大型对象列表。

Boolean 与任何其他基元包装器 class 一样具有自然顺序。假先于真。由于您希望 isWorking() returns 首先为真,因此我们需要反转条件。

car = car.stream()
        .sorted(Comparator.comparing(x -> ! x.isWorking()))
        .collect(Collectors.toList());
System.out.println("Working Cars First: " + car);

正如 Nikolas Charalambidis 在评论中指出的那样,Comparator 也可以写成 Comparator.comparing(Car::isWorking).reversed(),这可能感觉更自然,更符合通常的比较器。