Stream.max()如何处理相等性?
虽然我怀疑答案是“它未指定”……
如果Stream
有多个“最大/最低”元素, Comparator
传递给max或min方法认为相等(返回0
),是否指定了哪个元素将被找到?
确实很难从文档中提取明确的陈述。 如果我们试图从“减少”过程的一般描述和文档的类似提示中得出结论,那么我们总觉得我们可能做了太多的解释。
但是, Brian Goetz 对此问题有一个明确的陈述,他对Stream API非常权威:
如果对流进行排序(例如从数组或List获得的流),则在多个最大元素的情况下返回第一个最大元素; 只有当流是无序的时才允许选择任意元素。
遗憾的是,在Stream.max
的文档中没有做出这样一个明确的声明,但至少它符合我们的实现经验和知识(我们这些看过源代码的人) 。 不要忘记,实际的考虑,因为很容易说“选择任何而不是第一”通过unordered().max(comparator)
与当前的事态而不是说“先选择而不是任何”如果允许选择max
首先是一个任意元素。
在阅读完源代码之后,我认为应该是根据集合顺序找到的第一个最大的元素。 我们可以查看Stream.max(Comparator super T> comparator)
的源代码,实现类是ReferencePipeline.max
@Override public final Optional max(Comparator super P_OUT> comparator) { return reduce(BinaryOperator.maxBy(comparator)); }
你可以看到,当你调用Stream.max
,你的意思是调用Stream.reduce(BinaryOperator
并查看BinaryOperator.maxBy(comparator)
的源代码
public static BinaryOperator maxBy(Comparator super T> comparator) { Objects.requireNonNull(comparator); return (a, b) -> comparator.compare(a, b) >= 0 ? a : b; }
很明显,当a
等于b
,它返回a
。 因此,当Stream中有多个“最大/最低”元素时,根据收集顺序,“最大/最低”元素应该是第一个“最大/最低”元素
有一个例子在吹,只供您参考。
List 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);