我正在学习Java 8 Stream API的新手,
我想编写一个程序,使用IntStream
查找整数数组中的偶数,所以我提出了这个解决方案,
int[] numbers = {1,2,3,4,5,6,7,8,9,10};
IntStream.of(numbers).filter(i -> i%2 == 0).forEach(System.out::println);
这对我来说是正常的。
但是如何修改filter
以跳过从numbers
检查的某些数组索引?
例如,
如果我想跳过numbers[1]
被检查是否均匀,那我该怎么办?
因为过滤器中的i
是数组元素的值而不是它们的索引。
是否可以这样做?
答案 0 :(得分:8)
创建数组索引的流,并在映射到数组元素之前对其进行过滤:
int[] numbers = ...;
IntStream.range(0, numbers.length).filter(i -> i!=1)
.map(i -> numbers[i]).forEach(System.out::println);
如果你需要先按索引过滤掉一些元素,有些按值过滤,你可以在地图前面有一个过滤器,在后面有一个过滤器。
如果你需要检查同一过滤器中的索引和值,那么我认为最好的方法是创建一个类来保存这两个值:
class IndexedValue {
private int index, value;
IndexedValue(int index, int value) {
this.index = index ;
this.value = value ;
}
int getIndex() { return index ;}
int getValue() { return value ;}
}
然后你可以做
int[] numbers = ... ;
IntStream.range(0, numbers.length).map(i -> new IndexedValue(i, numbers[i]))
.filter(v -> v.getIndex() == 1 || v.getValue() % 2 == 0)
.forEach(System.out::println);
答案 1 :(得分:3)
@ James_D答案的变体。
想象一下,如果我们可以避免使用诸如IndexedValue之类的情境类,因为我们是愚蠢的比喻或其他东西。
好吧,想象一下:
int[] numbers = ... ;
IntStream.range(0, numbers.length)
// an anonymous class is defined at this juncture
// for the sake of discussion, said class is named
// Whatever (FF8 reference).
.mapToObj(i -> new Object() {
final int index = i;
final int value = numbers[i];
})
// IntStream translated to Stream<Whatever>
.filter(v -> v.index != 1)
// Stream<Whatever> with non-1 indices
.filter(v -> v.value % 2 == 0)
// Stream<Whatever> with even values
.mapToInt(v -> v.value)
// Stream<Whatever> to IntStream
.forEach(System.out::println)
;
声明: 我知道这是因为我厌倦了一次,并亲自尝试过。 无法保证此代码适用于非JavaC编译器。 (显然,Eclipse的类型推断并不像javac那样性感。无论如何。[FF8参考])
答案 2 :(得分:2)
作为替代解决方案,您可以使用迭代器获得相同的结果。
我是Enumerables的作者,它使用Stream熟悉的功能包装可迭代集合。它提供了一个具有索引参数的过滤方法。
int[] numbers = {1,2,3,4,5,6,7,8,9,10};
IntStream stream = IntStream.of(numbers);
Enumerable<Integer> enumerable = new Enumerable(() -> stream.iterator());
Enumerable<Integer> evens = enumerable.filter((x, i) -> x % 2 == 0 && i != 1);
return evens.toList().stream();