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



因此,在运行这段代码时

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并引发异常?

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

(对于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;
    }
}

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

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



请参阅JDK-8048689错误报告。

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

10-09 02:09