如何检查流<T>是否已排序?

2022-09-04 02:10:50

使用 ,很容易:Iterable<T>

T last = null;
for (T t : iterable) {
    if (last != null && last.compareTo(t) > 0) {
        return false;
    }
    last = t;
}
return true;

但是我想不出一种干净的方式来做同样的事情,以避免在没有必要的时候消耗所有元素。Stream<T>


答案 1

有几种方法可以循环访问流的连续对。例如,您可以检查此问题。当然,我最喜欢的方法是使用我写的

boolean unsorted = StreamEx.of(sourceStream)
                           .pairMap((a, b) -> a.compareTo(b) > 0)
                           .has(true);

这是短路操作:一旦发现错误排序,它就会立即完成。此外,它也适用于并行流。


答案 2

您可以获取 Stream 的基础拆分器,并检查它是否具有 SORTED 特征。由于它是一个终端操作,因此您无法使用 Stream after(但您可以从此拆分器创建另一个,另请参阅使用 Java 8 JDK 将迭代转换为 Stream)。

例如:

Stream<Integer> st = Stream.of(1, 2, 3);
//false
boolean isSorted = st.spliterator().hasCharacteristics(Spliterator.SORTED);

Stream<Integer> st = Stream.of(1, 2, 3).sorted();
//true
boolean isSorted = st.spliterator().hasCharacteristics(Spliterator.SORTED);

我的示例显示,仅当您从报告特征的源获取 Stream 或在管道上的某个点调用时,才会显示该特征。SORTEDSORTEDsorted()

有人可能会争辩说,它创建了一个流,但是对于迭代应用的函数的语义一无所知。这同样适用于 。Stream.iterate(0, x -> x + 1);SORTEDStream.of(...)

如果管道是无限的,那么这是知道的唯一方法。如果不是,并且拆分器不报告此特征,则需要遍历元素并查看它是否不满足您要查找的排序特征。

这是您已经使用迭代器方法完成的工作,但随后您需要使用 Stream 的某些元素(在最坏的情况下,所有元素)。您可以使用一些额外的代码使任务可并行化,然后由您来决定它是否值得...


推荐