我正在嘗試從 Set (HashSet) 中洗掉一些物件,但前提是它們也存在于 List (LinkedList) 中。如何使用 Java 8 功能(流)來實作這一點。
Set<MyObject> theSet -> want to remove items that are present in the list
List<MyObject> theList
我已經覆寫了 MyObject 的 equals 和 hashcode(僅使用幾個欄位來比較相等性)。
uj5u.com熱心網友回復:
如果您的集合是可變的,您可以從集合中洗掉串列中存在的所有條目,如下所示:
theSet.removeAll(theList);
假設您的集合是不可變的,那么您可以使用流過濾它,從而導致新集合缺少串列中存在的條目,如下所示:
var newSet = theSet.stream()
.filter(n -> !theList.contains(n))
.collect(Collectors.toSet());
對于 Java 11 ,您可以通過組合為過濾謂詞使用方法參考:
var newSet = theSet.stream()
.filter(Predicate.not(theList::contains))
.collect(Collectors.toSet());
關于性能的小說明
兩種方法(removeAll 和 via 流)都在O(N * M)中運行,其中N是 的大小,theSet
M是的大小theList
。它歸結為兩個嵌套的for回圈。
一個簡單的增強是變成一個集合并將線性包含檢查的成本降低到O(1)theList
的漸近運行時間。
var numsToExclude = new HashSet<>(theList);
var newSet = theSet.stream()
.filter(Predicate.not(numsToExclude::contains))
.collect(Collectors.toSet());
uj5u.com熱心網友回復:
您可以從界面中查看removeIf()
方法。Collection
所以你可以這樣說:
theSet.removeIf(theList::contains)
它還將回傳一個boolean
指示是否洗掉了任何元素。
uj5u.com熱心網友回復:
我懷疑流與考慮流開銷的簡單回圈一樣快。你總是必須遍歷整個串列,所以我會這樣做。這假定原始集是不可變的。
List<Integer> list = List.of(1,2,5,8,9,10);
Set<Integer> set = Set.of(3,4,8,2,1);
Set<Integer> result = new HashSet<>(set);
for(int val : list) {
result.remove(val);
}
System.out.println("Before: " set);
System.out.println("After: " result);
印刷
Before: [1, 8, 4, 3, 2]
After: [3, 4]
由于 Sets 不能保存重復項,因此在洗掉串列中遇到重復項不會影響結果。因此,如果您可以將它們收集在 aSet
而不是 a中List
,它可能會提供一些改進。
最后,你Object
要被洗掉必須覆寫equals
并且hashCode
上述作業。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/486314.html
上一篇:按相似的子字串對字串進行分組