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