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

问题描述 投票:0回答:2

我有一个

Person
的清单。

我想找到一个具有工作且具有最大年龄的人,否则返回具有最大年龄的任何人。

我写了以下代码。

这样可以吗?或者可以有更好的方法吗?

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));
java list java-8 stream java-stream
2个回答
1
投票

我有一个人员列表。我想找到一个人要么有最大年龄的工作,要么返回最大年龄的人。

可以通过创建中间映射、使用收集器partioningBy()

并提供收集器
maxBy()
作为下游,以
单次
通过列表来完成。

此组合将创建一个 map,其中包含 两个条目,其中键为

false
true
以及类型为 Optional<Person>
values
。因为
maxBy()
会产生可选结果。

首先,我们必须通过应用

filter()
来摆脱空可选。

然后我们可以按键相反的顺序对这些条目进行排序,这样

true
将出现在
false
之前(自然顺序:
false -> true
)。 IE。 在职人员年龄最大的优先。

最后一步是应用

findFirst()
并从结果映射条目中提取值。

因为我们只对两个条目进行排序,所以不会造成任何有形的开销,并且代码将运行线性时间(提醒:

maxBy()
运行于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 }

在线演示的链接


0
投票

这个问题的一个观点是,你想要“最伟大”的人,就业的人比失业的人多,如果都就业或失业,年长的人比年轻的人更大。

这转化为带有简单组合比较器的简单、单通道

max
操作:

Person person = personList.stream()
        .max(Comparator.comparing(Person::isEmployed).thenComparing(Person::getAge))
        .orElse(null);
© www.soinside.com 2019 - 2024. All rights reserved.