java - 从排序流中获取拆分器会引发异常

标签 java java-8 java-stream spliterator

根据 Spliterator#getComparator 的文档, 它指出

If this Spliterator's source is SORTED by a Comparator, returns that Comparator. If the source is SORTED in natural order, returns null. Otherwise, if the source is not SORTED, throws IllegalStateException.

Implementation Requirements:

The default implementation always throws IllegalStateException.

Returns: a Comparator, or null if the elements are sorted in the natural order.

Throws: IllegalStateException - if the spliterator does not report a characteristic of SORTED.

所以在运行这段代码的时候

Spliterator<Integer> spliterator = Stream.of(1, 2, 3).sorted().spliterator();

System.out.println((spliterator.characteristics() & Spliterator.SORTED) == Spliterator.SORTED);
System.out.println(spliterator.getComparator());

我得到:

true
null

到目前为止一切顺利。现在这样做:

Spliterator<Integer> spliterator = Stream.of(1, 2, 3).sorted(Comparator.naturalOrder()).spliterator();

System.out.println((spliterator.characteristics() & Spliterator.SORTED) == Spliterator.SORTED);
System.out.println(spliterator.getComparator());

它输出false并抛出异常:

Exception in thread "main" java.lang.IllegalStateException
    at java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.getComparator(StreamSpliterators.java:259)
    at SpliteratorTest.main(SpliteratorTest.java:10)

为什么会输出false并抛出异常?

根据文档,它不应该给我提供给 sorted()Comparator 吗?

(这也发生在 reverseOrder()comparing(identity()) 等中)。

最佳答案

内部流使用 StreamOpFlag 枚举,这与拆分器标志有些不同。使用 java.util.stream.StreamOpFlag.fromCharacteristics(Spliterator<?>) 方法转换标志,其实现如下:

static int fromCharacteristics(Spliterator<?> spliterator) {
    int characteristics = spliterator.characteristics();
    if ((characteristics & Spliterator.SORTED) != 0 && spliterator.getComparator() != null) {
        // Do not propagate the SORTED characteristic if it does not correspond
        // to a natural sort order
        return characteristics & SPLITERATOR_CHARACTERISTICS_MASK & ~Spliterator.SORTED;
    }
    else {
        return characteristics & SPLITERATOR_CHARACTERISTICS_MASK;
    }
}

似乎流 API 不需要在内部没有明确自然排序的拆分器的 SORTED 特性,因此它没有保留。实际上,文档中从未指定 sorted(comparator).spliterator() 必须 返回具有 SORTED 特性的拆分器。 spliterator 文档说,如果它具有 SORTED 特性,则它必须返回比较器,但没有要求具有 SORTED 特性的情况,因此取决于实现。这在未来可能会改变,但这不是错误。

更新:刚刚注意到在 JDK-9 中,在 spliterator() 方法的文档中有一个明确的声明 added:

The returned spliterator should report the set of characteristics derived from the stream pipeline (namely the characteristics derived from the stream source spliterator and the intermediate operations). Implementations may report a sub-set of those characteristics. For example, it may be too expensive to compute the entire set for some or all possible stream pipelines.

查看 JDK-8048689 错误报告。

关于java - 从排序流中获取拆分器会引发异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31159161/

相关文章:

Java 8 计算具有多个值的对象

java - 在另一个类中更改 TextArea

java - Clojure 中的默认十进制文字不是 BigDecimal 类型有什么原因吗?

Java:绝对值的最大值和最小值

java - 使用 JaVers 进行异步审核

java - 执行 Observables 映射

java-stream, map, keys 与对象无关

java - 将 Runnable 转换为 Supplier

java - 如何确保使用接口(interface)实现公共(public)静态函数

java - 如何在使用 Stream 的同时将 Long 转换为 BigDecimal