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

2022-09-03 02:25:51

虽然我怀疑答案是“它没有指定”......

如果 a 中有多个“最大/最低”元素,传递给 maxmin 的方法认为这些元素相等(返回),是否在某个地方指定了将找到哪个元素?StreamComparator0


答案 1

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

但是,Brian Goetz就此事发表了明确声明,他是Stream API的权威:

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

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


答案 2

看完源代码,我觉得应该是第一个最大的元素会按照收集顺序找到。我们可以查看的源代码,实现类是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.maxStream.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;
    }

很明显,当相等时,它会返回。因此,当流中有多个“最大/最低”元素时,根据收集顺序,“最大/最低”元素应该是第一个“最大/最低”元素aba

有一个例子在吹,仅供您参考。

        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);

推荐