嵌套流异常

jos*_*osh 2 java java-8 java-stream

我想返回所有字符串的字符串排列。当我使用下面的代码时,我得到了java.lang.IllegalStateException: stream has already been operated upon or closed。您能告诉我这种方法有什么问题吗?

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();
}
Run Code Online (Sandbox Code Playgroud)

样品测试

Stream<String> patterns = getMyPatterns(
            Stream.of("a1", "a2"),
            Stream.of("b1", "b2"),
            Stream.of("c1", "c2"));
Run Code Online (Sandbox Code Playgroud)

Hol*_*ger 5

作为暗示别人,您使用的是流s2s3forEach多次。

另一方面,在返回Stream之前收集结果列表是没有意义的。forEach无论如何,如果还有其他更合适的操作,则不应该使用。

您只需要收集要与上一个合并的Stream。最好首先解决两个流的组合来实现:

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));
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以轻松地递归使用此方法来解决合并三个Streams的任务:

public Stream<String> getMyPatterns(Stream<String> s1,Stream<String> s2,Stream<String> s3) {
    return getMyPatterns(getMyPatterns(s1, s2), s3);
}
Run Code Online (Sandbox Code Playgroud)

这只会收集尽可能少的内容,即不会收集第一个Stream,因此只有在消耗返回的Stream时才开始消耗它。

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(", ")));
Run Code Online (Sandbox Code Playgroud)
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));
}
Run Code Online (Sandbox Code Playgroud)