在Java 8中使用IntStream.filter时如何跳过特定的数组索引

时间:2015-02-13 18:19:01

标签: java java-8

我正在学习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是数组元素的值而不是它们的索引。

是否可以这样做?

3 个答案:

答案 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();