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

具体问题:

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)

我错过了什么?


当前回答

关于生成反向IntStream的具体问题:

从Java 9开始,你可以使用三个参数版本的IntStream.iterate(…):

IntStream.iterate(10, x -> x >= 0, x -> x - 1).forEach(System.out::println);

// Out: 10 9 8 7 6 5 4 3 2 1 0

地点:

IntStream。迭代(int seed, IntPredicate hasNext, IntUnaryOperator next);

种子——初始元素; hasNext -应用于元素的谓词,以确定何时 流必须终止; Next -应用于前一个元素的函数,以生成一个 新元素。

其他回答

最通用和最简单的反转列表的方法是:

public static <T> void reverseHelper(List<T> li){

 li.stream()
.sorted((x,y)-> -1)
.collect(Collectors.toList())
.forEach(System.out::println);

    }

关于生成反向IntStream的具体问题:

从Java 9开始,你可以使用三个参数版本的IntStream.iterate(…):

IntStream.iterate(10, x -> x >= 0, x -> x - 1).forEach(System.out::println);

// Out: 10 9 8 7 6 5 4 3 2 1 0

地点:

IntStream。迭代(int seed, IntPredicate hasNext, IntUnaryOperator next);

种子——初始元素; hasNext -应用于元素的谓词,以确定何时 流必须终止; Next -应用于前一个元素的函数,以生成一个 新元素。

你可以定义自己的收集器,按相反的顺序收集元素:

public static <T> Collector<T, List<T>, List<T>> inReverse() {
    return Collector.of(
        ArrayList::new,
        (l, t) -> l.add(t),
        (l, r) -> {l.addAll(r); return l;},
        Lists::<T>reverse);
}

像这样使用它:

stream.collect(inReverse()).forEach(t -> ...)

我使用ArrayList在前向顺序有效地插入收集项(在列表的末尾),和番石榴列表。Reverse用于有效地提供列表的反向视图,而无需复制另一个列表。

下面是自定义收集器的一些测试用例:

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;

import org.hamcrest.Matchers;
import org.junit.Test;

import com.google.common.collect.Lists;

public class TestReverseCollector {
    private final Object t1 = new Object();
    private final Object t2 = new Object();
    private final Object t3 = new Object();
    private final Object t4 = new Object();

    private final Collector<Object, List<Object>, List<Object>> inReverse = inReverse();
    private final Supplier<List<Object>> supplier = inReverse.supplier();
    private final BiConsumer<List<Object>, Object> accumulator = inReverse.accumulator();
    private final Function<List<Object>, List<Object>> finisher = inReverse.finisher();
    private final BinaryOperator<List<Object>> combiner = inReverse.combiner();

    @Test public void associative() {
        final List<Object> a1 = supplier.get();
        accumulator.accept(a1, t1);
        accumulator.accept(a1, t2);
        final List<Object> r1 = finisher.apply(a1);

        final List<Object> a2 = supplier.get();
        accumulator.accept(a2, t1);
        final List<Object> a3 = supplier.get();
        accumulator.accept(a3, t2);
        final List<Object> r2 = finisher.apply(combiner.apply(a2, a3));

        assertThat(r1, Matchers.equalTo(r2));
    }

    @Test public void identity() {
        final List<Object> a1 = supplier.get();
        accumulator.accept(a1, t1);
        accumulator.accept(a1, t2);
        final List<Object> r1 = finisher.apply(a1);

        final List<Object> a2 = supplier.get();
        accumulator.accept(a2, t1);
        accumulator.accept(a2, t2);
        final List<Object> r2 = finisher.apply(combiner.apply(a2, supplier.get()));

        assertThat(r1, equalTo(r2));
    }

    @Test public void reversing() throws Exception {
        final List<Object> a2 = supplier.get();
        accumulator.accept(a2, t1);
        accumulator.accept(a2, t2);

        final List<Object> a3 = supplier.get();
        accumulator.accept(a3, t3);
        accumulator.accept(a3, t4);

        final List<Object> r2 = finisher.apply(combiner.apply(a2, a3));

        assertThat(r2, contains(t4, t3, t2, t1));
    }

    public static <T> Collector<T, List<T>, List<T>> inReverse() {
        return Collector.of(
            ArrayList::new,
            (l, t) -> l.add(t),
            (l, r) -> {l.addAll(r); return l;},
            Lists::<T>reverse);
    }
}

我建议使用jOOλ,它是一个很棒的库,为Java 8流和lambdas添加了许多有用的功能。

然后您可以执行以下操作:

List<Integer> list = Arrays.asList(1,2,3,4);    
Seq.seq(list).reverse().forEach(System.out::println)

就这么简单。它是一个非常轻量级的库,非常值得添加到任何Java 8项目中。

How about reversing the Collection backing the stream prior?

import java.util.Collections;
import java.util.List;

public void reverseTest(List<Integer> sampleCollection) {
    Collections.reverse(sampleCollection); // remember this reverses the elements in the list, so if you want the original input collection to remain untouched clone it first.

    sampleCollection.stream().forEach(item -> {
      // you op here
    });
}