我该如何检查Stream <T>是否已排序?

Tav*_*nes 12 java java-8 java-stream

有了Iterable<T>,很容易:

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

但我想不出一个干净的方法来做同样的事情Stream<T>,避免消耗所有元素,而不必.

Tag*_*eev 9

有几种方法可以迭代连续的流对.例如,您可以查看此问题.当然我最喜欢的方法是使用我写的库:

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

这是短路操作:一旦发现错误,它就会完成.它也适用于并行流.


Ale*_* C. 5

您可以获取Stream的基础分离器,并检查它是否具有SORTED特性。由于这是一种终端操作,因此您不能在之后使用Stream(但是您可以从此拆分器中创建另一个,请参见使用Java 8 JDK将Iterable转换为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);
Run Code Online (Sandbox Code Playgroud)

我的示例显示,SORTED仅当您从报告SORTED特征的来源获取流或sorted()在管道上的某个点调用时,特征才会出现。

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

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

这是您使用迭代器方法所做的,但是随后您需要使用Stream的某些元素(最坏的情况是所有元素)。您可以使用一些额外的代码使任务可并行化,然后由您自己决定是否值得...

  • 如您的示例所示,可以在不具有SORTED特征的情况下有效地对流进行排序...如果流具有SORTED特征,则可以对其进行排序,但是,如果流没有SORTED特征,则可以对它进行排序,也可以不对它进行排序... (2认同)
  • 此外,即使 spliterator 是 `SORTED` 也不意味着它是根据自然顺序排序的。你至少也应该检查一下`getComparator()`。 (2认同)

tob*_*s_k 1

您可以使用allMatch多行 lambda,根据前一个值检查当前值。不过,您必须将最后一个值包装到数组中,以便 lambda 可以修改它。

// infinite stream with one pair of unsorted numbers
IntStream s = IntStream.iterate(0, x -> x != 1000 ? x + 2 : x - 1);
// terminates as soon as the first unsorted pair is found
int[] last = {Integer.MIN_VALUE};
boolean sorted = s.allMatch(x -> {
    boolean b = x >= last[0]; last[0] = x; return b; 
});
Run Code Online (Sandbox Code Playgroud)

或者,只需从流中获取iterator并使用简单的循环。

  • 现在尝试使用 `IntStream s = IntStream.of(1, 2, 3);` 和 `s.parallel().allMatch(...)`.. (2认同)