2017-02-24 75 views
1

我對streamString的不同操作有不同的問題。Java 8 - 不同的字符串流 - IllegalStateException

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) 

但如果我寫的這部分代碼是這樣的:

Stream<String> names = Arrays.asList("NAME A", "NAME B", "NAME A").stream(); 
final Stream<String> distinct = names.distinct(); 
System.out.println(distinct.collect(Collectors.joining(","))); 

一切都OK。的不同

文檔說:

流不同() 返回該流的組成的不同元素的流(根據的Object.Equals(對象))。 對於有序流,選擇不同的元素是穩定的(對於重複的元素,保留在遇到順序中首先出現的元素)。對於無序流,不做穩定性保證。 這是一個有狀態的中間操作。

我做錯了什麼?

感謝您的幫助

+0

@choasia,請仔細閱讀 – MateuszW90

+1

是不是因爲您忽略了由中間操作生成的新流,而且一個流只能操作一次。 – choasia

回答

4

文檔和錯誤信息給你的原因:stream has already been operated upon or closeddistinct() Returns a stream

當你調用namesdistinct,它回報有不同元素的新流。但是,您再collect。但是這個流已經被distinct運算符消耗掉了。

在你的第二個例子中,你對它正確,因爲你收集了獨特的流。

所以基本上,你總是在你的第二個例子做到這一點像,或簡稱

names.distinct().collect(Collectors.joining(",")); 
4

基本上,您使用的流API錯誤。

您忽略了您不應該做的distinct()的返回值。它與任何不直接在參數上操作的方法類似,但返回它的修改版本。

慣用的版本將是

String names = Arrays.asList("NAME A", "NAME B", "NAME A"). 
    stream().distinct().collect(Collectors.joining(","); 
System.out.println(names); 
3

由於the documentation說:

甲流應(調用中間或操作終端流操作)只有一次。這排除了例如「分叉」流,其中相同的源饋送兩個或更多個管線,或者多個遍歷同一個流。如果流實現可能會拋出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