Java 8 Stream - .max()带有重复项

And*_*ose 21 java java-8 java-stream

所以我有一组对象,它们的步长变量可以是1到4.

public class MyClass {
    private Long step;

    //other variables, getters, setters, etc.
}
Run Code Online (Sandbox Code Playgroud)

Collection<MyClass> myOjbects = /*get collection*/;

然后我想MyClass从集合中获得具有最大步长值的一个实例,所以我这样做:

final Optional<MyClass> objectWithMaxStep =
   myObjects.stream().max(Comparator.comparing(MyClass::getStep));
Run Code Online (Sandbox Code Playgroud)

但是,在某些情况MyClass下,集合中将有多个实例,其步长等于4.

所以,我的问题是,如何确定返回哪个实例Optional,或者当流中的多个对象具有要比较的最大值时是否抛出异常?

max()函数的Java 8文档未指定在这种情况下将发生的情况.

ka4*_*eli 17

max实现减少集合maxBy:

 public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
        Objects.requireNonNull(comparator);
        return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
    }
Run Code Online (Sandbox Code Playgroud)

在这里comparator.compare(a, b) >= 0 ? a : b你可以看到,当2个元素相等时,即compare返回0,则返回第一个元素.因此,在您的案件将被退回首先在收集MyClass对象最高step.

更新:正如用户在评论中正确提到的8472,您不应该依赖javadocs未明确指定的实现.但是你可以在max方法上编写单元测试,以了解标准java库中的逻辑是否已经改变.

  • 只要javadocs没有指定行为,你就不应该真正依赖于实现. (13认同)

dka*_*zel 10

由于文档未指定排序,因此在未来版本的JVM或JVM的不同实现中,顺序可能不同.

如果您关心哪一个被退回,那么我的建议是编写您自己的减少操作或收集器,以按照您的意愿行事.这样未来的实现就无法改变它,你可以明确地说明会发生什么.

  • 这两个例子不可能更加不同.有一个合理的论点,即最小/最大的事情只是一个疏忽,因此我们有可能纠正这一点.`toList()`事情不是疏忽 - 这是重点!所以我们改变它的可能性是零.完全缺乏承诺是设计 - 最大化实施灵活性.(我们提供了简单的替代方案.如果你想要一个`ArrayList`,你可以使用`toCollection(ArrayList :: new)`.) (9认同)
  • 这里有`sorted()`和`distinct()`的行为联系.如果流是有序的,则排序操作是稳定的,否则不稳定.类似地,如果对流进行排序,则"distinct"操作将返回每个等价类的_first_实例.如果订购了流,则还原还会考虑遇到订单.缺少的是min/max不承诺 - 但可以说他们应该这样做. (7认同)