如何在 Java 流中应用多个条件

How to apply multiple Conditions in Java streams

我有一个列表 Person

我想找一个有工作最大年龄的人,否则return任何最大年龄.

下面这段代码是我写的

这样好还是可以有更好的方法。

List <Person> personList;
    
Person person = personList.stream()
    .filter(p -> p.isEmployed())
    .max(Comparator.comparing(Person::getAge))
    .orElse(personList.stream()
                .max(Comparator.comparing(Person::getAge))
                .orElse(null));

I have a list of Person. I want to find a person either have employment with maximum age else return person with maximum age.

可以通过创建一个中间映射,使用收集器partioningBy() and providing collector maxBy()在列表中单次完成下游。

此组合将创建一个 map,其中包含 两个条目,键为 falsetrue 以及 类型 Optional<Person>。因为 maxBy() 产生一个可选结果。

首先,我们必须通过应用 filter().

来摆脱空可选

然后我们可以按倒序对这些条目进行排序,这样true就会排在false之前(自然顺序:false -> true)。 IE。 就业者年龄最大者优先

最后一步是应用 findFirst() 并从生成的映射条目中提取值。

因为我们只对两个条目进行排序,所以不会造成任何有形的开销,并且代码将运行线性时间(提醒: maxBy() 运行s in O(n) 时间,单次遍历数据集)。

List<Person> personList =
    List.of(new Person(23, false), new Person(32, true),
            new Person(36, true), new Person(39, false),
            new Person(19, false), new Person(21, true));

Person person = personList.stream()
    .collect(Collectors.partitioningBy(Person::isEmployed, // intermediate map Map<Boolean, Optional<Person>>
        Collectors.maxBy(Comparator.comparing(Person::getAge))))
    .entrySet().stream()
    .filter(entry -> entry.getValue().isPresent())
    .sorted(Map.Entry.<Boolean, Optional<Person>>comparingByKey().reversed())
    .findFirst()              // Optional<Map.Entry<Boolean, Optional<Person>>>
    .map(Map.Entry::getValue) // Optional<Optional<Person>>
    .map(Optional::get)       // Optional<Person>
    .orElse(null);

System.out.println(person);

输出:

Person {  age = 36, isEmployed = true }

A link to the Online Demo