一般问题:什么是反转流的正确方法?假设我们不知道流由什么类型的元素组成,反转任何流的通用方法是什么?

具体问题:

IntStream提供了在特定范围内生成整数的range方法。range(-range, 0),现在我想反转它,从0到负切换范围将不起作用,我也不能使用Integer::比较

List<Integer> list = Arrays.asList(1,2,3,4);
list.stream().sorted(Integer::compare).forEach(System.out::println);

使用IntStream,我将得到这个编译器错误

错误:(191,0)ajc: IntStream类型中的sorted()方法不适用于参数(Integer::compare)

我错过了什么?


当前回答

ArrayDeque在堆栈中比stack或LinkedList更快。"push()"将元素插入到Deque的前面

 protected <T> Stream<T> reverse(Stream<T> stream) {
    ArrayDeque<T> stack = new ArrayDeque<>();
    stream.forEach(stack::push);
    return stack.stream();
}

其他回答

以下是我想出的解决方案:

private static final Comparator<Integer> BY_ASCENDING_ORDER = Integer::compare;
private static final Comparator<Integer> BY_DESCENDING_ORDER = BY_ASCENDING_ORDER.reversed();

然后使用这些比较器:

IntStream.range(-range, 0).boxed().sorted(BY_DESCENDING_ORDER).forEach(// etc...

最简单的解决方案是使用List::listIterator和Stream::generate

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
ListIterator<Integer> listIterator = list.listIterator(list.size());

Stream.generate(listIterator::previous)
      .limit(list.size())
      .forEach(System.out::println);

作为参考,我正在考虑同样的问题,我想以相反的顺序连接流元素的字符串值。

itemList = {last, middle, first} =>第一个,中间,最后一个

我开始从comonad或Stuart Marks的ArrayDeque收集器中使用colltingandthen的中间收集,尽管我对中间收集不满意,然后再次使用流式

itemList.stream()
        .map(TheObject::toString)
        .collect(Collectors.collectingAndThen(Collectors.toList(),
                                              strings -> {
                                                      Collections.reverse(strings);
                                                      return strings;
                                              }))
        .stream()
        .collect(Collector.joining());

所以我迭代了Stuart Marks的答案,它使用了收集器。factory,它有一个有趣的结束项。

itemList.stream()
        .collect(Collector.of(StringBuilder::new,
                             (sb, o) -> sb.insert(0, o),
                             (r1, r2) -> { r1.insert(0, r2); return r1; },
                             StringBuilder::toString));

由于在这种情况下,流不是并行的,组合器不是那么相关,我使用插入无论如何为了代码的一致性,但这并不重要,因为它将取决于哪个stringbuilder是第一个构建的。

我看了看StringJoiner,但是它没有插入方法。

反转字符串或任何数组

(Stream.of("abcdefghijklm 1234567".split("")).collect(Collectors.collectingAndThen(Collectors.toList(),list -> {Collections.reverse(list);return list;}))).stream().forEach(System.out::println);

Split可以根据分隔符或空格进行修改

反转流的正确通用方法是什么?

如果流没有指定遇到顺序,就不要这样做。 (! s.spliterator () .hasCharacteristics (java.util.Spliterator.ORDERED))