Stream.max()如何处理相等性?

虽然我怀疑答案是“它未指定”……

如果Stream有多个“最大/最低”元素, Comparator传递给max或min方法认为相等(返回0 ),是否指定了哪个元素将被找到?

确实很难从文档中提取明确的陈述。 如果我们试图从“减少”过程的一般描述和文档的类似提示中得出结论,那么我们总觉得我们可能做了太多的解释。

但是, Brian Goetz 对此问题有一个明确的陈述,他对Stream API非常权威:

如果对流进行排序(例如从数组或List获得的流),则在多个最大元素的情况下返回第一个最大元素; 只有当流是无序的时才允许选择任意元素。

遗憾的是,在Stream.max的文档中没有做出这样一个明确的声明,但至少它符合我们的实现经验和知识(我们这些看过源代码的人) 。 不要忘记,实际的考虑,因为很容易说“选择任何而不是第一”通过unordered().max(comparator)与当前的事态而不是说“先选择而不是任何”如果允许选择max首先是一个任意元素。

在阅读完源代码之后,我认为应该是根据集合顺序找到的第一个最大的元素。 我们可以查看Stream.max(Comparator comparator)的源代码,实现类是ReferencePipeline.max

  @Override public final Optional max(Comparator comparator) { return reduce(BinaryOperator.maxBy(comparator)); } 

你可以看到,当你调用Stream.max ,你的意思是调用Stream.reduce(BinaryOperator accumulator)

并查看BinaryOperator.maxBy(comparator)的源代码

  public static  BinaryOperator maxBy(Comparator 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);