[英]Is it worth using distinct() with collect(toSet())
將流的元素收集到集合中時,是否還有優勢(或缺點)在流上指定.distinct()
? 例如:
return items.stream().map(...).distinct().collect(toSet());
鑒於該集合已經刪除了重復項,這似乎是多余的,但它是否提供任何性能優勢或劣勢? 答案取決於流是並行/順序還是有序/無序?
根據javadoc , distinct
是一個有狀態的中間操作。
如果你確實有.distinct
緊跟着.collect
,那么它並沒有真正增加任何好處。 也許如果.distinct
實現比Set
重復檢查更.distinct
,你可能會獲得一些好處,但是如果你收集到一個集合,你最終會得到相同的結果。
另一方面,如果.distinct
發生在.map
操作之前,並且該特定映射是一項昂貴的操作,那么您可能會獲得一些收益,因為您整體處理的數據較少。
雖然你有相同的結果,但它們不會做同樣的事情: toSet()
使用HashSet
,你失去了初始排序,如果需要,它可以保留不同的東西:
來自javadoc :
保持並行管道中不同()的穩定性相對昂貴(要求操作充當完全屏障,具有大量緩沖開銷),並且通常不需要穩定性。 如果您的情境的語義允許,使用無序流源(例如generate(Supplier))或使用BaseStream.unordered()刪除排序約束可以顯着提高並行管道中distinct()的執行效率。 如果需要與遇到順序的一致性,並且您在並行管道中使用distinct()遇到性能不佳或內存利用率,則切換到使用BaseStream.sequential()的順序執行可能會提高性能。
如果你需要穩定性,那么它是distinct()
。 之后使用toSet()
將是無用的(如果API不需要)。
但是,如果你有一個equals
實現部分相等的equals
:
class F {
int a;
int b;
@Override int hashCode() {return Objects.hashCode(a);}
@Override boolean equals(Object other) {
if (other == this) return true;
if (!(other instanceof F)) return false;
return a == ((F)other).a;
}
}
如果你有a = F(10, 1)
和b = F(10, 2)
它們是等於。 但並非所有領域都是平等的。
如果在列表中你有(b, a)
toSet()
您將無法始終擁有此訂單。 你可能有(b,a)等 (b, a)
。 然而,這假設了一些先決條件(順序等)。
注意:這可以使用TreeSet
和適當的compareTo
方法完成。
distinct會調用equals / hashcode來分隔項目,之后toSet會做同樣的事情(即使在不需要之后,但是toSet也不能真正知道),所以基本上你只是重復調用。 它應該表現稍差IMO。 測量也很容易。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.