Stream.max() 如何处理相等性?
2022-09-03 02:25:51
确实很难仅从文档中提取明确的语句。如果我们试图从“Reduce”过程的一般描述和文档的类似提示中得出结论,总会觉得我们可能做了太多的解释。
但是,Brian Goetz就此事发表了明确声明,他是Stream API的权威:
如果流是有序的(例如从数组或List获取的流),则在有多个最大元素的情况下,它将返回第一个最大元素;只有当流是无序的,才允许它选取任意元素。
遗憾的是,在 的文档中没有做出如此明确的声明,但至少它符合我们的经验和实现知识(我们这些查看源代码的人)。不要忘记,实际的考虑,因为很容易说“选择任何而不是首先”通过当前事态,而不是说“首先选择而不是任何”,如果首先被允许选择任意元素。Stream.max
unordered().max(comparator)
max
看完源代码,我觉得应该是第一个最大的元素会按照收集顺序找到。我们可以查看的源代码,实现类是Stream.max(Comparator<? super T> comparator)
ReferencePipeline.max
@Override
public final Optional<P_OUT> max(Comparator<? super P_OUT> comparator) {
return reduce(BinaryOperator.maxBy(comparator));
}
你可以看到,当你调用时,你的意思是调用Stream.max
Stream.reduce(BinaryOperator<P_OUT> accumulator)
并查看源代码BinaryOperator.maxBy(comparator)
public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator);
return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
}
很明显,当相等时,它会返回。因此,当流中有多个“最大/最低”元素时,根据收集顺序,“最大/最低”元素应该是第一个“最大/最低”元素a
b
a
有一个例子在吹,仅供您参考。
List<Student> list = Arrays.asList(new Student("s1", 1), new Student("s2", 5), new Student("s3", 3), new Student("s4", 5));
// it should be student of 's2'
list.stream().max(Comparator.comparing(Student::getScore));
// it should be student of 's4'
list.stream().reduce((a, b) -> Comparator.comparing(Student::getScore).compare(a, b) > 0 ? a : b);