我对\b
stream
的{{1}}采取截然不同的行动有疑问。
String
然后,我收到了例外:
Stream<String> names = Arrays.asList("NAME A", "NAME B", "NAME A").stream();
names.distinct();
System.out.println(names.collect(Collectors.joining(",")));
但是,如果我像这样编写这部分代码:
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:229)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at com.Test.main(Test.java:62)
一切都好。
distinct的文档说:
Stream distinct() 返回由此流的不同元素(根据Object.equals(Object))组成的流。 对于有序流,不同元素的选择是稳定的(对于重复元素,保留在遇到顺序中首先出现的元素。)对于无序流,不进行稳定性保证。 这是一个有状态的中间操作。
我做错了什么?
感谢您的帮助
答案 0 :(得分:4)
基本上你使用的是流API错误。
你忽略了你不应该做的distinct()
的返回值。它类似于任何不直接对参数进行操作的方法,但会返回它的修改版本。
惯用版将是
String names = Arrays.asList("NAME A", "NAME B", "NAME A").
stream().distinct().collect(Collectors.joining(",");
System.out.println(names);
答案 1 :(得分:4)
文档和错误消息说明了原因:stream has already been operated upon or closed
和distinct() Returns a stream
当您在distinct
上致电names
时,会返回一个包含不同元素的新流。但是再次collect
再次names
。但是此流已由distinct
运算符使用。
在第二个示例中,您正确地使用它,因为您收集了不同的流。
所以基本上,你总是要像第二个例子那样,或者简而言之
names.distinct().collect(Collectors.joining(","));
答案 2 :(得分:3)
正如the documentation所说:
应该只对一个流进行操作(调用中间或终端流操作)。例如,这排除了&#34;分叉&#34;流,相同的源提供两个或多个管道,或同一流的多个遍历。如果流实现检测到正在重用流,则可以抛出
IllegalStateException
。
因此,一旦您在流上调用distinct()
,就不能再使用它。而是使用返回的流。当您以source.stream().intermediateOp().anotherIntermediateOp().terminalOp()
形式链接操作时,永远不会出现此错误。
所以在你的情况下,它将是
String s = Arrays.asList("NAME A", "NAME B", "NAME A").stream()
.distinct().collect(Collectors.joining(","));
System.out.println(s);
但你可以直接使用
String s = Stream.of("NAME A", "NAME B", "NAME A")
.distinct().collect(Collectors.joining(","));
System.out.println(s);
而不是使用Arrays.asList
。