Nested stream exception

josh :

I would like to return permutations of strings from all strings. When i use below code, i get java.lang.IllegalStateException: stream has already been operated upon or closed. Could you please tell me what is wrong with this approach ?

public Stream<String> getMyPatterns(
        Stream<String> s1,
        Stream<String> s2,
        Stream<String> s3) {
    List<String> out = new ArrayList<String>();
    s1.collect(Collectors.toList()).forEach(item1 -> {
        s2.collect(Collectors.toList()).forEach(item2 -> {
            s3.collect(Collectors.toList()).forEach(item3 -> {
                out.add(item1 + "." + item2 + "." + item3);
            });
        });
    });
    return out.stream();
}

Sample test

Stream<String> patterns = getMyPatterns(
            Stream.of("a1", "a2"),
            Stream.of("b1", "b2"),
            Stream.of("c1", "c2"));
Holger :

As hinted by others, you are using the Streams s2 and s3 within forEach multiple times.

On the other hand, collecting the result list before returning a Stream, is pointless. You shouldn’t use forEach anyway, when there are other, more suitable operations.

You only need to collect the Stream you want to combine with the previous one. This is best accomplished by first solving it for a combination of two Streams:

public Stream<String> getMyPatterns(Stream<String> s1, Stream<String> s2) {
    List<String> s2List = s2.collect(Collectors.toList());
    return s1.flatMap(item1 -> s2List.stream().map(item2 -> item1+'.'+item2));
}

Then, you can easily use this method recursively to solve the task of combining three Streams:

public Stream<String> getMyPatterns(Stream<String> s1,Stream<String> s2,Stream<String> s3) {
    return getMyPatterns(getMyPatterns(s1, s2), s3);
}

This collects only as little as necessary, i.e. it won’t collect the first Stream, so its consumption will only start when the returned Stream is consumed.

Stream<String> patterns = getMyPatterns(
    Stream.of("a1", "a2").peek(s -> System.out.println("consuming "+s)),
    Stream.of("b1", "b2"),
    Stream.of("c1", "c2"));

System.out.println("start consuming result Stream");
System.out.println(patterns.collect(Collectors.joining(", ")));
start consuming result Stream
consuming a1
consuming a2
a1.b1.c1, a1.b1.c2, a1.b2.c1, a1.b2.c2, a2.b1.c1, a2.b1.c2, a2.b2.c1, a2.b2.c2

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=127210&siteId=1