2014-04-01 53 views
9

我想知道有關Java 8流(Stream<E>),它們有以下幾種方法:在Java 8流中沒有索引的原因是什麼?

  • forEach(Consumer<? super E> action)
  • forEachOrdered(Consumer<? super E> action)

什麼反對不提供以下簽名的論點?

  • forEachOrdered(BiConsumer<Integer, ? super E> action)
    • 那麼這將返回該項目的索引流和項目本身英寸

有了這個超載將有可能實際使用流奉命萬一指數。

我真的很好奇,看看有什麼理由反對它。

編輯Iterator<E>forEachRemaining相同,可能還有更多的類。
如果沒有一個類提供這樣的選項,那麼我懷疑它已被考慮用於Java 8並被拒絕。

+0

http://stackoverflow.com/a/18563928/829571 – assylias

+0

@assylias感謝您的插件。這促使我去清理那個答案。 :-) –

回答

5

Stream s和Iterator s不必是有限的。 Stream::generateStream::iterate返回無限Stream s。你將如何處理無限流的索引?讓索引溢出負數?使用BigInteger(可能會耗盡內存)?

沒有一個好的解決方案來處理無限流的索引,所以設計者(正確地說,在我看來)把它留在了API之外。

+3

Collectors.counting()會出現同樣的問題,使用'long',但它可能會溢出。所以在這一點上,或者你的論點不夠好,或者對'Collectors.counting()'也是一個很好的論點。我沒有看到任何其他問題,儘管無限流和迭代器(除了它們從不停止) – skiwi

+1

@skiwi好吧,如果您嘗試在'Collectors'中的一半方法在無限的'Stream'上使用,的內存或引入無限循環。 'Collectors'提供了處理大部分用例的實用方法。大多數時候,你實際上不會處理無限的'Stream',所以'Collectors'是有保證的。 – Jeffrey

8

索引每個元素需要順序分配索引。這將破壞並行操作的重點,因爲每個操作都必須同步才能獲得其索引。

+0

+1。索引對於並行流是無意義的。 –

+1

我正在專門討論有序流,如果您決定支持您的答案,您能解釋爲什麼無法在平行排序的流中進行索引嗎? – skiwi

+0

如果您想要,您可以在消費者本身中保留一個櫃檯,以便按照順序執行已知的操作,那麼爲什麼還需要額外的簽名? –

2

添加一個提供索引的方法將需要所有實現方法被加倍以使其中一個維護一個索引而另一個沒有。除了在API中可見,還有更多。如果你很好奇,你可以看看內部接口java.util.stream.Sink<T>的類型樹來獲得一個想法。所有這些都會受到影響。另一種方法是始終保持一個索引,即使它不是必需的。

它增加了一個模糊性。索引是否反映來源索引,即在過濾時不會改變,或者在最終流中是的位置?另一方面,您總是可以插入從項目類型到在項目鏈中任何位置持有項目和索引的類型的映射。這將清除模糊性。該解決方案的限制與JRE提供的解決方案具有的限制相同。

如果是Iterator,答案就更簡單了。由於forEachRemaining必須作爲default接口方法提供,因此它不能添加索引的維護。所以在它被調用的時候,它並不知道到目前爲止已經消耗了多少物品。並且在那個時候開始計數爲零,忽略所有以前的項目將是許多開發人員會質疑更多的功能。

0

我已閱讀所有上述答案,但是,我個人不同意他們。我認爲應該增加一些方法(例如indexed()),它可以按順序執行,即使是並行流,因爲這種方法將被快速驗證,不需要並行執行。您可以通過地圖添加'索引'。例如:

List<String> list = N.asList("a", "b", "c"); 
final AtomicLong idx = new AtomicLong(0); 
list.stream().map(e -> Indexed.of(idx.getAndIncrement(), e)).forEach(N::println); 

或者你也可以使用第三方庫:AbacusUtil,代碼爲:

List<String> list = N.asList("a", "b", "c"); 
Stream.of(list).indexed().forEach(N::println); 
// output: 
// [0]=a 
// [1]=b 
// [2]=c 

披露:我AbacusUtil的開發商。

相關問題