一般问题:什么是反转流的正确方法?假设我们不知道流由什么类型的元素组成,反转任何流的通用方法是什么?
具体问题:
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)
我错过了什么?
此方法适用于任何流,并且兼容Java 8:
Stream<Integer> myStream = Stream.of(1, 2, 3, 4, 5);
myStream.reduce(Stream.empty(),
(Stream<Integer> a, Integer b) -> Stream.concat(Stream.of(b), a),
(a, b) -> Stream.concat(b, a))
.forEach(System.out::println);
我就是这么做的。
我不喜欢创建一个新集合并反向迭代它的想法。
IntStream#映射的想法是非常整洁的,但我更喜欢IntStream#迭代方法,因为我认为倒计时到零的想法更好地表达了迭代方法,更容易理解从后面到前面的数组行走。
import static java.lang.Math.max;
private static final double EXACT_MATCH = 0d;
public static IntStream reverseStream(final int[] array) {
return countdownFrom(array.length - 1).map(index -> array[index]);
}
public static DoubleStream reverseStream(final double[] array) {
return countdownFrom(array.length - 1).mapToDouble(index -> array[index]);
}
public static <T> Stream<T> reverseStream(final T[] array) {
return countdownFrom(array.length - 1).mapToObj(index -> array[index]);
}
public static IntStream countdownFrom(final int top) {
return IntStream.iterate(top, t -> t - 1).limit(max(0, (long) top + 1));
}
下面是一些测试来证明它是有效的:
import static java.lang.Integer.MAX_VALUE;
import static org.junit.Assert.*;
@Test
public void testReverseStream_emptyArrayCreatesEmptyStream() {
Assert.assertEquals(0, reverseStream(new double[0]).count());
}
@Test
public void testReverseStream_singleElementCreatesSingleElementStream() {
Assert.assertEquals(1, reverseStream(new double[1]).count());
final double[] singleElementArray = new double[] { 123.4 };
assertArrayEquals(singleElementArray, reverseStream(singleElementArray).toArray(), EXACT_MATCH);
}
@Test
public void testReverseStream_multipleElementsAreStreamedInReversedOrder() {
final double[] arr = new double[] { 1d, 2d, 3d };
final double[] revArr = new double[] { 3d, 2d, 1d };
Assert.assertEquals(arr.length, reverseStream(arr).count());
Assert.assertArrayEquals(revArr, reverseStream(arr).toArray(), EXACT_MATCH);
}
@Test
public void testCountdownFrom_returnsAllElementsFromTopToZeroInReverseOrder() {
assertArrayEquals(new int[] { 4, 3, 2, 1, 0 }, countdownFrom(4).toArray());
}
@Test
public void testCountdownFrom_countingDownStartingWithZeroOutputsTheNumberZero() {
assertArrayEquals(new int[] { 0 }, countdownFrom(0).toArray());
}
@Test
public void testCountdownFrom_doesNotChokeOnIntegerMaxValue() {
assertEquals(true, countdownFrom(MAX_VALUE).anyMatch(x -> x == MAX_VALUE));
}
@Test
public void testCountdownFrom_givesZeroLengthCountForNegativeValues() {
assertArrayEquals(new int[0], countdownFrom(-1).toArray());
assertArrayEquals(new int[0], countdownFrom(-4).toArray());
}