一般问题:什么是反转流的正确方法?假设我们不知道流由什么类型的元素组成,反转任何流的通用方法是什么?
具体问题:
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)
我错过了什么?
一般问题:
流不存储任何元素。
因此,如果不将元素存储在某个中间集合中,就不可能以相反的顺序迭代元素。
Stream.of("1", "2", "20", "3")
.collect(Collectors.toCollection(ArrayDeque::new)) // or LinkedList
.descendingIterator()
.forEachRemaining(System.out::println);
更新:改变LinkedList为ArrayDeque(更好),详情请看这里
打印:
3
20
2
1
顺便说一下,使用sort方法是不正确的,因为它排序,而不是反转(假设流可能有无序元素)
具体问题:
我发现这很简单,更容易和直观(复制@Holger评论)
IntStream.iterate(to - 1, i -> i - 1).limit(to - from)
cyclops-react StreamUtils有一个反向流方法(javadoc)。
StreamUtils.reverse(Stream.of("1", "2", "20", "3"))
.forEach(System.out::println);
它的工作原理是收集到一个数组列表,然后使用可以向任意方向迭代的ListIterator类,在列表上向后迭代。
如果你已经有了一个List,它会更有效率
StreamUtils.reversedStream(Arrays.asList("1", "2", "20", "3"))
.forEach(System.out::println);
这里的许多解决方案对IntStream进行排序或反转,但这不必要地需要中间存储。斯图尔特·马克斯的解决方案是可行的:
static IntStream revRange(int from, int to) {
return IntStream.range(from, to).map(i -> to - i + from - 1);
}
它正确地处理溢出以及,通过这个测试:
@Test
public void testRevRange() {
assertArrayEquals(revRange(0, 5).toArray(), new int[]{4, 3, 2, 1, 0});
assertArrayEquals(revRange(-5, 0).toArray(), new int[]{-1, -2, -3, -4, -5});
assertArrayEquals(revRange(1, 4).toArray(), new int[]{3, 2, 1});
assertArrayEquals(revRange(0, 0).toArray(), new int[0]);
assertArrayEquals(revRange(0, -1).toArray(), new int[0]);
assertArrayEquals(revRange(MIN_VALUE, MIN_VALUE).toArray(), new int[0]);
assertArrayEquals(revRange(MAX_VALUE, MAX_VALUE).toArray(), new int[0]);
assertArrayEquals(revRange(MIN_VALUE, MIN_VALUE + 1).toArray(), new int[]{MIN_VALUE});
assertArrayEquals(revRange(MAX_VALUE - 1, MAX_VALUE).toArray(), new int[]{MAX_VALUE - 1});
}
关于生成反向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 -应用于前一个元素的函数,以生成一个
新元素。