Let's say I have an int array and I want to find all pairs that sum to zero. In the old days I would do something like this:
public static int count(int[] a) {
int cnt = 0;
int N = a.length;
for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; j++) {
if (a[i] + a[j] == 0) {
cnt++;
}
}
}
return cnt;
}
Now I'm having some trouble converting this to streams.
I tried the following approach but I get a IllegalStateException:
final IntStream stream1 = Arrays.stream(a);
final IntStream stream2 = Arrays.stream(a);
long res = stream1.flatMap(i -> stream2.filter(j -> (j + i == 0))).count();
change stream2.filter
to Arrays.stream(a)
- the Stream would be closed the second time you would try to process it.
But you are not counting correctly anyway, it should be:
IntStream.range(0, a.length)
.flatMap(x -> Arrays.stream(a).skip(x + 1).filter(j -> j + a[x] == 0))
.count();
Streams
are non-reusable so you can't define them once and keep reusing. This is why storing them in variables is considered a bad practice.
You need to create them on the spot:
long res = Arrays.stream(a)
.flatMap(i -> Arrays.stream(a).filter(j -> (j + i == 0)))
.count();
Also, in order to fully reflect the provided implementation and avoid duplicates, you would need to skip
some elements at the beginning of each nested Stream
:
long res = IntStream.range(0, a.length)
.flatMap(i -> Arrays.stream(a).skip(i + 1).filter(j -> (j + a[i] == 0)))
.count();
If you want to extract them to variables, you would need to use a Supplier
which will serve as a factory for our Streams
. Each get
call creates a new Stream
instance:
final Supplier<IntStream> s = () -> Arrays.stream(a);
long res = s.get()
.flatMap(i -> s.get().filter(j -> (j + i == 0)))
.count();
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