簡體   English   中英

使用distinct()和collect(toSet())是否值得

[英]Is it worth using distinct() with collect(toSet())

將流的元素收集到集合中時,是否還有優勢(或缺點)在流上指定.distinct() 例如:

return items.stream().map(...).distinct().collect(toSet());

鑒於該集合已經刪除了重復項,這似乎是多余的,但它是否提供任何性能優勢或劣勢? 答案取決於流是並行/順序還是有序/無序?

根據javadocdistinct是一個有狀態的中間操作。

如果你確實有.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)等
  • 使用distinct()可以保留此信息,例如: (b, a)

然而,這假設了一些先決條件(順序等)。

注意:這可以使用TreeSet和適當的compareTo方法完成。

distinct會調用equals / hashcode來分隔項目,之后toSet會做同樣的事情(即使在不需要之后,但是toSet也不能真正知道),所以基本上你只是重復調用。 它應該表現稍差IMO。 測量也很容易。

暫無
暫無

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

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