I have two streams which I must materialize into two lists to get the permutations from both streams:
public Stream<Permutation> getAll() { Stream.Builder<Permutation> all = Stream.builder(); // unfortunately, I must collect it into a list var list1 = IntStream.iterate(0, d -> d - 1).limit(1000000).boxed().collect(Collectors.toList()); var list2 = IntStream.iterate(0, d -> d + 1).limit(1000000).boxed().collect(Collectors.toList()); // I must use a classic loop (and cannot operate on those streams) to avoid java.lang.IllegalStateException for(var l1: list1) { for(var l2: list2) { // the permutation class consists of two int properties all.add(new Permutation(l1, l2)); } } return all.build(); }
Is there a way to avoid to materialize list1
and list2
and operate only on those streams to return the permutations? I have tried it but I get
java.lang.IllegalStateException: stream has already been operated upon or closed
Therefore I have materialized the two lists and used a classic loop. However, I would like to improve the performance by doing the following steps:
- avoid the materialization of
list1
andlist2
- and maybe also use parallelStream for
list1
andlist2
to get the permutations faster
Is this possible? If so, how?
EDIT:
Thanks to @Andreas for the solution which works so far. However, I wonder how I can create a permutation from two getAll()-streams without the need to materialize it in between:
// The `Permutations` class holds two `Permuation`-instances. Stream<Permutations> allPermutations(){ Stream<Permutation> stream1 = getAll(); Stream<Permutation> stream2 = getAll(); // returns java.lang.IllegalStateException: stream has already been operated upon or closed return stream1.flatMap(s1->stream2.map(s2->new Permutations(s1,s2)); }
Answer
You can do it like this:
public Stream<Permutation> getAll() { return IntStream.iterate(0, d -> d - 1).limit(1000000).boxed() .flatMap(l1 -> IntStream.iterate(0, d -> d + 1).limit(1000000) .mapToObj(l2 -> new Permutation(l1, l2))); }
The caller can decide whether or not to use parallel processing:
// Sequential Stream<Permutation> stream = getAll(); // Parallel Stream<Permutation> stream = getAll().parallel();
No need to call sequential()
, since iterate()
returns a new sequential IntStream
.