I am learning and new to Java 8 Stream API,
I wanted to write a program to find even numbers in integer array using IntStream
, so I came up with this solution,
int[] numbers = {1,2,3,4,5,6,7,8,9,10};
IntStream.of(numbers).filter(i -> i%2 == 0).forEach(System.out::println);
and this is working correctly for me.
but how can I modify the filter
to skip certain array indexes from being checked from numbers
?
for example,
if i want to skip numbers[1]
from being checked if it even or not then what should i do ?
because i
in the filter are the values of the array elements not their indexes.
is it possible to do so ?
Here is a tutorial on how you can skip on some elements of an array? Suppose we want to skip every third element. We need to store this data in an array. C++ has one keyword known as continue which skips the current iteration and continues, whenever it sees the keyword continue.
The skip(n) method is an intermediate operation that discards the first n elements of a stream. The n parameter can't be negative, and if it's higher than the size of the stream, skip() returns an empty stream.
The limit method of the Stream class introduced in Java 8 allows the developer to limit the number of elements that will be extracted from a stream. The limit method is useful in those applications where the user wishes to process only the initial elements that occur in the stream.
Create an AtomicInteger for index. Get the Stream from the array using Arrays. stream() method. Map each elements of the stream with an index associated with it using map() method where the index is fetched from the AtomicInteger by auto-incrementing index everytime with the help of getAndIncrement() method.
Create a stream of the array indices instead, and filter it, before mapping to the array elements:
int[] numbers = ...;
IntStream.range(0, numbers.length).filter(i -> i!=1)
.map(i -> numbers[i]).forEach(System.out::println);
If you need first to filter some elements out by index, and some out by value, you can have one filter before the map and one after.
If you need to check both the index and the value in the same filter, then I think the best way is to create a class to hold both values:
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 ;}
}
and then you can do
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);
A variant of @James_D's answer.
Imagine if we could avoid the usage of situational classes such as IndexedValue, because we are silly billies or something.
Well, imagine no more:
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)
;
Disclaimer: I know this because I got bored once and tried it myself. There is no guarantee that this code will work with non-JavaC compilers. (Apparently, Eclipse's type inference is not as sexy as javac's. Whatever. [FF8 reference])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With