Reputation: 831
I am trying to join two streams together. I ran into the problem that my stream closes and I don't understand why. Couldn't anyone please explain to me why the following happens.
The code below doesn't work. I get an exception on the flatMap function that the stream is already closed.
private Stream<KeyValuePair<T, U>> joinStreams(Stream<T> first, Stream<U> second) {
return
first
.map(x -> second
.map(y -> new KeyValuePair<T, U>(x, y))
)
.flatMap(x -> x);
}
When I first collect a list from the second stream and then grab a stream from that list it does work. See the example below.
private Stream<KeyValuePair<T, U>> joinStreams(Stream<T> first, Stream<U> second) {
List<U> secondList = second.collect(Collectors.toList());
return
first
.map(x -> secondList.stream()
.map(y -> new KeyValuePair<T, U>(x, y))
)
.flatMap(x -> x);
}
I can't figure out why this happens. Could anyone please explain this?
Edit:
Example of the code calling this function.
List<Integer> numbers1 = Arrays.asList(1, 2);
List<Integer> numbers2 = Arrays.asList(3, 4);
List<KeyValuePair<Integer, Integer>> combined = joinStreams(numbers1.stream(), numbers2.stream())
.collect(Collectors.toList());
// Expected result
// 1 3
// 1 4
// 2 3
// 2 4
Upvotes: 4
Views: 2666
Reputation: 393851
The problem is that your code attempts to process the second Stream
twice (once for each element of the first Stream
). A Stream
can only be processed once, just like an Iterator
can only iterate over the elements of the underlying class once.
If your first Stream
had only one element, the code would work, since the second Stream
would only be processed once.
In the code that does work, you produce a new Stream
(from secondList
) for each element of the first Stream
, so each Stream
is processed once, regardless of how many elements are in the first Stream
.
Upvotes: 5