我想為一個集合創建一個擴展函式來檢查一個集合是否包含任何已定義集合的專案。我考慮了兩種實作:
infix fun <T> Iterable<T>.containsAny(values: Iterable<T>): Boolean = any(values::contains)
或者
infix fun <T> Iterable<T>.containsAny(values: Iterable<T>): Boolean = intersect(values).isNotEmpty()
問題是哪種方式更有效,為什么?有沒有更好的解決方案?
uj5u.com熱心網友回復:
第一種方法any是O(n*m),除非引數 Iterable 是一個 Set,在這種情況下它是O(n)。
第二種方法intersect是O(n)。
所以第二種方法要快得多,除非引數已經是一個 Set 或者兩個輸入都非常小以至于值得重復迭代以避免將接收者 Iterable 復制到 MutableSet。
可以通過以下方式改進O(n)方式以允許提前退出行為any:
infix fun <T> Iterable<T>.containsAny(values: Iterable<T>): Boolean =
any(values.toSet()::contains)
并進一步避免不必要的設定副本:
infix fun <T> Iterable<T>.containsAny(values: Iterable<T>): Boolean =
any((values as? Set<T> ?: values.toSet())::contains)
如果接收器 Iterable 通常大于引數 Iterable,您可能希望交換哪個是集合以及哪個正在迭代。
uj5u.com熱心網友回復:
查看實作intersect將占用更多記憶體,因為它創建了一個中間集。
我的猜測any會更有效,因為它非常簡單。最終,最好只使用 JMH 對您的用例進行基準測驗。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/422645.html
標籤:
上一篇:具有不等大小組的有效遞回隨機抽樣
