我有一个
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));
我有一个人员列表。我想找到一个人要么有最大年龄的工作,要么返回最大年龄的人。
可以通过创建中间映射、使用收集器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 }
这个问题的一个观点是,你想要“最伟大”的人,就业的人比失业的人多,如果都就业或失业,年长的人比年轻的人更大。
这转化为带有简单组合比较器的简单、单通道
max
操作:
Person person = personList.stream()
.max(Comparator.comparing(Person::isEmployed).thenComparing(Person::getAge))
.orElse(null);