但即使resourceMemory
是一個線程安全集合,您的代碼仍然被破壞,因爲您的filter
條件與終端操作之間存在干擾。 .filter(o -> !resourceMemory.contains(o))
查詢您在終端操作中修改的相同列表,並且不應該很難理解即使使用線程安全集合,這也能如何制動:
兩個或多個線程可能會處理過濾器,並發現該元素不包含在列表中,那麼所有的人都會添加的元素,矛盾沒有重複你的意圖明顯。
你可以訴諸forEachOrdered
這將執行的操作順序和非併發:
body.getSurroundings().parallelStream()
.filter(o -> o instanceof ResourcePoint)
.map(o -> (ResourcePoint)o)
.forEachOrdered(o -> {// not recommended, just for explanation
if(!resourceMemory.contains(o))
resourceMemory.add(o);
});
這將工作,很明顯你怎麼可以加入到這一行動中的另一個列表,但它遠是遠推薦的編碼風格。此外,這個終端動作與所有處理線程同步的事實會破壞並行處理的任何潛在的好處,特別是作爲該流管道的最昂貴的操作是在一個LinkedList
將(必須)發生單線程調用contains
。
收集流元素到列表中正確的方法是通過,顧名思義,collect
:
List<ResourcePoint> resourceMemory
=body.getSurroundings().parallelStream()
.filter(o -> o instanceof ResourcePoint)
.map(o -> (ResourcePoint)o)
.distinct() // no duplicates
.collect(Collectors.toList()); // collect into a list
這不返回LinkedList
,但是你應該認真重新考慮你是否真的需要一個LinkedList
。在所有病例的99%中,你沒有。如果您真的需要需要LinkedList
,您可以用Collectors.toCollection(LinkedList::new)
替換Collectors.toList()
。
現在,如果您確實必須添加到您的控件之外創建的現有列表(可能已包含元素),則應考慮上述事實,您必須確保單線程訪問非線程安全無論如何,所以從並行流中完全沒有任何好處。在大多數情況下,它更有效地從該名單獨立讓流工作,並在單線程一步之後添加的結果:
Set<ResourcePoint> newElements=
body.getSurroundings().parallelStream()
.filter(o -> o instanceof ResourcePoint)
.map(o -> (ResourcePoint)o)
.collect(Collectors.toCollection(LinkedHashSet::new));
newElements.removeAll(resourceMemory);
resourceMemory.addAll(newElements);
在這裏,我們收集到LinkedHashSet
這意味着遭遇秩序的維護和排序刪除新元素中的重複項,然後在新元素上使用removeAll
刪除目標列表中的現有元素(這裏我們從臨時集合的哈希集性質中受益),最後,將新元素添加到目標列表中,如上所述,無論如何,對於不是線程安全的目標集合,必須發生單線程。
使用此解決方案將newElements
添加到其他目標集合很容易,比在流處理期間編寫用於生成兩個列表的自定義收集器要容易得多。但請注意,上面所寫的流操作過於勉強以至於不能從並行處理中獲益。您需要大量的元素來補償最初的多線程開銷。甚至有可能沒有任何數字能夠得到回報。
您可以使用'peek()'或自定義收集器。 –
你的意思是'instanceof ResourcePoint'或'o.getClass()== ResourcePoint.class'嗎?決定一個,但不要使用混淆實際意圖的'o.getClass()。equals(ResourcePoint.class)'。此外,使用並行流時,您的代碼會以多種方式被破解。請仔細閱讀https://docs.oracle.com/javase/8/docs/api/?java/util/stream/package-summary.html。 – Holger
問題的嚴格答案是'.forEach(o - > {resourceMemory.add(o); myOtherList.add(o);})'。但請注意Holger的評論。您需要更多地瞭解您想要解決此問題的真正目標。 – Tunaki