【问题标题】:Why Java 8 Stream interface does not have min() no-parameter version?为什么 Java 8 Stream 接口没有 min() 无参数版本?
【发布时间】:2017-12-16 20:13:14
【问题描述】:

java.util.stream.Stream 接口有两个版本的sorted 方法——sorted() 按自然顺序排序元素和sorted(Comparator)。为什么min() 方法没有引入Stream 接口,从自然排序的角度来看,它会返回最小的元素?

【问题讨论】:

  • 已经给出的答案很有帮助,但还没有完全达到重点。所以,sorted 方法有 2 个版本——sorted()sorted(Comparator)。在有sorted的对应版本时,min()没有与min(Comparator)一起引入,在我看来有点不一致。应该是有原因的。
  • Stream.sorted() 是个错误。应该只有Stream.sorted(Comparator)
  • @ZhekaKozlov 我也这么认为,但我找不到任何关于此的邮件列表讨论
  • @Eugene 他们只是没有勇气承认这一点:)
  • @ZhekaKozlov 哈哈!我对此表示怀疑,希望在这里等待 Stuart Marks

标签: java java-8 java-stream


【解决方案1】:

应该清楚的是,对于minmaxsorted,向Stream 添加不需要比较器的方法会导致失去泛型类型安全性。原因是 Java 语言的当前版本不支持将方法限制为特定参数化的实例,即将它们限制为可比较元素的流。

所以问题可能是反过来的,为什么 sorted() 允许这种潜在的类型安全中断?

我无法深入了解开发人员的想法,但有趣的一点是,排序已经被特殊处理了很长时间。随着泛型的引入,可以强制执行没有Comparator 的排序只能对具有可比较元素的集合或数组进行尝试。然而,特别是在实现泛型集合时,开发人员可能会面临无法使用泛型元素类型创建数组的事实。可能还有其他情况,开发人员遇到形式上不可比较类型的数组或集合,而包含的元素肯定是可比较的。如前所述,我无法深入了解开发人员的想法,说出考虑了哪些场景。

但是

但这不仅仅是向后兼容性。 List.sort(Comparator),在 Java 8 中引入,也被指定为接受 null 作为“自然顺序”的参数,所以现在我们有另一种情况,实现者可能必须在没有保证可比较元素的编译时类型的情况下对数据进行排序.

所以在排序方面,已经有很多机会避开类型系统。但是Stream.sorted(Comparator) 是唯一不接受null 比较器的排序方法。因此,在不指定Comparator.naturalOrder() 的情况下按自然顺序排序只能使用不带参数的sorted()。顺便说一句,只有一个带有null 比较器的已排序输入和请求sorted() 没有比较器是Stream 实现检测到不需要排序的唯一情况,即它不比较比较器并且不检查Comparator.naturalOrder()

一般来说,比较器的类型安全性非常弱。例如。 Collections.reverseOrder() 返回任意类型的比较器,不要求类型可比较。因此,您可以使用max(Collections.reverseOrder()) 代替min() 来请求最小值,而不管流的正式类型如何。或者使用Collections.reverseOrder(Collections.reverseOrder()) 来获得与Comparator.naturalOrder() 等效的任意类型。同样,Collator 实现了 Comparator<Object>,无论出于何种原因,尽管它只能比较 Strings。

【讨论】:

  • limit them to streams of comparable elements 是什么意思?一种说法是,除非有一个类型T extends Comparable...,否则你不能拥有一个方法max 的可见性(访问)让我们说?
  • @Eugene: 是的,一种假设的说法是“这个方法只能被调用,如果目标可以分配给Stream<T extends Comparable<? super T>>”。已经有一种语法允许为this 的类型添加注释,所以在语法方面,变化不会那么大。但从语义上讲,这将是一大步。
【解决方案2】:

我认为这只会污染 API。有人可以说“为什么没有最大无参数版本”“为什么没有 CharStream” 并且就可以提供的东西而言,它可以不断重复但决定最好不要。

对此有一个无参数的 min 方法:

someList.stream().min(Comparator.naturalOrder());

不会有什么不同。

因此最好只创建一个可重用方法,而不是用所有可能的东西污染 API。

【讨论】:

  • 可能的污染是一个好点,但不会引入无参数sorted()
【解决方案3】:

我认为 min() 只允许接受 Comparator 的签名,因为 Stream 可以是任何类型,甚至是您创建的类型。在这种情况下,不可能依赖自然顺序,因为您创建的类在您指定之前不能具有自然顺序。

如果在您使用的 Stream 类 IntStream 中,您会看到定义了一个不带参数的 min() 方法。这可以满足您的需求。如下:

public static void main (String... args){
        IntStream s=IntStream.of(1,2,3,4,5,6,7,8,9,10);
        System.out.println(s.min().getAsInt());
    }

【讨论】:

  • 嗯...好点,但sorted()也需要元素来实现Comparable,但它仍然被引入到接口中。
  • 我听到了。我也开始对这件事感到好奇。找出这一点的另一个线索,也许是 sorted 是一个中间操作,而 min/max 不是。但我真的想不出这有什么帮助
【解决方案4】:

Comparator.naturalOrder 用于此目的。它的存在(或其自定义实现)允许其他类保持简单,因为它们不必为 Comparator 字段中的空值实现特殊的代码路径。

它的类型也会强制流的 T 实现 Comparable。

【讨论】:

  • 是的,Comparator.naturalOrder() 在这种情况下毫无疑问会有所帮助,但它仍然不能完全回答问题(请参阅对主要问题的评论)。
猜你喜欢
  • 2015-10-08
  • 2017-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-28
  • 1970-01-01
相关资源
最近更新 更多