簡體   English   中英

深刻理解分裂者的特征

[英]Understanding deeply spliterator characteristics

為了嘗試深入理解java流和分裂器,我對spliterator特性有一些微妙的問題:

Q1: Stream.empty() vs Stream.of() (沒有args的Stream.of())

  • Stream.empty()SUBSIZED,SIZED
  • Stream.of()SUBSIZED, IMMUTABLE ,SIZED, ORDERED

為什么Stream.empty()不具有相同的特點Stream.of() 請注意,與Stream.concat()(特別是沒有ORDERED )一起使用時會產生影響。 我會說Stream.empty()不應該只有IMMUTABLE和ORDERED ,還要有DISTINCT和NONNULL 同樣有意義的Stream.of()只有一個參數有DISTICT

Q2: LongStream.of()沒有NONNULL

剛剛注意到NONNULL在LongStream.of不可用。 NONNULL不是所有LongStreamIntStreamDoubleStream的主要特征嗎?

Q3: LongStream.range(,) vs LongStream.range(,).boxed()

  • LongRange.range(,)SUBSIZED, IMMUTABLE,NONNULL ,SIZED,ORDERED, SORTED ,DISTINCT
  • LongStream.range(,).boxed()SUBSIZED,SIZED,ORDERED

為什么.boxed()失去了所有這些特征? 它不應該失去任何。

我知道.mapToObj()會失去NONNULL,IMMUTABLE和DISTICT ,但是.boxed() ......沒有意義。

Q4: .peek()失去IMMUTABLE和NONNULL

LongStream.of(1)SUBSIZED,IMMUTABLE,NONNULL,SIZED,... LongStream.of(1).peek()SUBSIZED,SIZED,...

為什么.peek()失去了這些特征? .peek不應該真的失去任何。

Q5: .skip() .limit()丟失了SUBSIZED,IMMUTABLE,NONNULL,SIZED

請注意,這些操作失去了SUBSIZED,IMMUTABLE,NONNULL,SIZED 為什么? 如果尺寸可用,那么也很容易計算最終尺寸。

Q6: .filter()失去IMMUTABLE,NONNULL

請注意,此操作失敗了SUBSIZED,IMMUTABLE,NONNULL,SIZED 丟失SUBSIZED和SIZED是有道理的,但其他兩個沒有意義。 為什么?


如果能夠深入理解分裂者的人能夠帶來一些清晰度,我將不勝感激。 謝謝。

我不得不承認,當我第一次嘗試找出特征的實際含義時,我也遇到了困難,並且感覺它們的意義在Java 8的實現階段沒有明確解決,並且由於這個原因而使用不一致。

考慮Spliterator.IMMUTABLE

表示元素源不能進行結構修改的特征值; 也就是說,無法添加,替換或刪除元素,因此在遍歷期間不會發生此類更改。

在這個列表中看到“替換”是很奇怪的,當談到List或數組時通常不會將其視為結構修改因此,接受數組(未克隆)的流和spliterator工廠報告IMMUTABLE ,如LongStream.of(…)Arrays.spliterator(long[])

如果我們更慷慨地將其解釋為“只要客戶無法觀察”,則對於CONCURRENT沒有顯着差異,因為在任何一種情況下, 某些元素將被報告給客戶而無需任何方式來識別它們是否在遍歷期間添加或是否因為刪除而未報告某些內容,因為無法回放分裂器並進行比較。

規范繼續:

不報告IMMUTABLECONCURRENT IMMUTABLE應該具有關於遍歷期間檢測到的結構干擾的文檔化策略(例如拋出ConcurrentModificationException )。

這是唯一相關的事情,報告, IMMUTABLECONCURRENT IMMUTABLE器保證永遠不會拋出ConcurrentModificationException 當然, CONCURRENT語義上排除了SIZED ,但這對客戶端代碼沒有任何影響。

實際上,這些特性並不用於Stream API中的任何內容,因此,使用它們不一致的地方永遠不會被注意到。

這也解釋了為什么每個中間操作都具有清除CONCURRENTIMMUTABLENONNULL特性的效果:Stream實現不使用它們,並且表示流狀態的內部類不維護它們。


同樣, NONNULL不會在任何地方使用,因此某些流沒有效果。 我可以LongStream.of(…)問題,直到內部使用Arrays.spliterator(long[], int, int)委托給
Spliterators.spliterator​(long[] array, int fromIndex, int toIndex, int additionalCharacteristics)

返回的spliterator始終報告SIZEDSUBSIZED的特征。 呼叫者可以為分裂者報告提供額外的特征。 (例如,如果已知數組將不會被進一步修改,請指定IMMUTABLE ;如果數組數據被視為具有遭遇順序,請指定ORDERED )。 通常可以使用方法Arrays.spliterator(long[], int, int) ,它返回一個報告SIZEDSUBSIZEDIMMUTABLEORDERED IMMUTABLE

注意(再次) IMMUTABLE特性的不一致使用。 它再次被視為必須保證不存在任何修改,同時, Arrays.spliterator以及Arrays.streamLongStream.of(…)將報告IMMUTABLE特性,即使是通過規范,也無法保證調用者不會修改他們的數組。 除非我們考慮將元素設置為不是結構修改,否則,整個區別再次變得無意義,因為數組不能在結構上進行修改。

它明確指出沒有NONNULL特征。 雖然原始值顯然不能為null ,而Spliterator.Abstract<Primitive>Spliterator類總是會注入NONNULL特性,但Spliterators.spliterator​(long[],int,int,int)返回的Spliterators.spliterator​(long[],int,int,int)器不會繼承自Spliterator.AbstractLongSpliterator

不好的是,這不能在不改變規格的情況下修復,好的是,它無論如何都沒有后果。


因此,如果我們忽略了CONCURRENTIMMUTABLENONNULL任何問題,這些問題沒有任何后果,我們有

SIZEDskiplimit 這是一個眾所周知的問題,Stream API實現了skiplimit的方式。 其他實現是可以想象的。 這也適用於無限流與limit的組合,其應具有可預測的大小,但是在當前實現的情況下,還沒有。

Stream.concat(…)Stream.empty()結合使用。 這聽起來是合理的空流結果順序施加約束。 Stream.concat(…)在只有一個輸入沒有順序時釋放順序的行為是值得懷疑的。 請注意,對於排序來說過於激進並不是什么新鮮事,請參閱此問答,關於首先被認為是故意的行為,但后來已經修復到Java 8,更新60.也許, Stream.concat應該在此時討論過時間也是......

.boxed()的行為很容易解釋。 當它像.mapToObj(Long::valueOf)一樣天真地實現時,它將簡單地失去所有知識,因為mapToObj不能假設結果仍然是排序的或不同的。 但是這已經用Java 9修復了。在那里, LongStream.range(0,10).boxed()具有SUBSIZED|SIZED|ORDERED|SORTED|DISTINCT特征,保留了與實現相關的所有特征。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM