[英]What is the best way to remove duplicates in an Array in Java?
我有一個對象數組需要刪除/過濾重復項。 我只是在Object元素上覆蓋equals&hachCode,然后將它們粘貼在Set中......但我認為我至少應該輪詢stackoverflow以查看是否有其他方法,或許某些其他API的聰明方法?
我同意你的方法來覆蓋hashCode()
和equals()
並使用實現Set
東西。
這樣做也使任何其他開發人員都清楚地知道需要非重復的特性。
另一個原因 - 您現在可以選擇最符合您需求的實施方案:
並且您不必更改代碼以在將來更改實現。
我在網上發現了這個
以下兩種方法允許您刪除ArrayList中的重復項。 removeDuplicate不維護removeDuplicateWithOrder維護訂單的順序,其中包含一些性能開銷。
removeDuplicate方法:
/** List order not maintained **/ public static void removeDuplicate(ArrayList arlList) { HashSet h = new HashSet(arlList); arlList.clear(); arlList.addAll(h); }
removeDuplicateWithOrder方法:
/** List order maintained **/ public static void removeDuplicateWithOrder(ArrayList arlList) { Set set = new HashSet(); List newList = new ArrayList(); for (Iterator iter = arlList.iterator(); iter.hasNext();) { Object element = iter.next(); if (set.add(element)) newList.add(element); } arlList.clear(); arlList.addAll(newList); }
覆蓋equals
和hashCode
並創建一個集合也是我的第一個想法。 在繼承層次結構中,無論如何都要對這些方法進行一些重寫,這是一種很好的做法。
我認為如果你使用LinkedHashSet
你甚至可以保留獨特元素的順序......
使用List distinctList
在第一次iterator
偶然發現時記錄元素,返回distinctList作為列表刪除所有重復項
private List removeDups(List list) {
Set tempSet = new HashSet();
List distinctList = new ArrayList();
for(Iterator it = list.iterator(); it.hasNext();) {
Object next = it.next();
if(tempSet.add(next)) {
distinctList.add(next);
}
}
return distinctList;
}
基本上,您需要一個LinkedHashSet<T>
實現,它支持List<T>
接口以進行隨機訪問。 因此,這就是你需要的:
public class LinkedHashSetList<T> extends LinkedHashSet<T> implements List<T> {
// Implementations for List<T> methods here
...
}
List<T>
方法的實現將訪問和操作底層的LinkedHashSet<T>
。 當一個人試圖通過List<T>
添加方法添加重復項時(拋出異常或在不同的索引處重新添加項目)將是選項:你可以選擇其中一個或者make可由班級用戶配置)。
我想重申傑森在評論中提出的觀點:
為什么要把自己放在那一點上?
為什么要將數組用於不應該重復的數據結構?
使用Set
或SortedSet
(當元素具有自然順序時)始終保持元素。 如果您需要保持插入順序,那么您可以使用已指出的LinkedHashSet
。
必須對某些數據結構進行后期處理通常是一種暗示,您應該首先選擇不同的數據結構。
當然,最初的帖子引出了一個問題,“你是如何獲得那個陣列(可能包含重復的條目)?”
您是否需要將陣列(帶有重復項)用於其他目的,或者您是否可以從頭開始使用Set?
或者,如果您需要知道每個值的出現次數,可以使用Map<CustomObject, Integer>
來跟蹤計數。 此外,Multimap類的Google Collections定義可能有用。
Set
肯定是你最好的選擇。 從數組中刪除東西(不創建新數組)的唯一方法是將它們清空,然后最后進行大量的空檢查。
從通用編程標准來看,您可以始終雙重枚舉集合,然后比較源和目標。
如果你的內部枚舉總是在源之后開始一個條目,那么它是相當有效的(偽代碼可以遵循)
foreach ( array as source )
{
// keep track where we are in the array
place++;
// loop the array starting at the entry AFTER the current one we are comparing to
for ( i=place+1; i < max(array); i++ )
{
if ( source === array[place] )
{
destroy(array[i]);
}
}
}
你可以說可以加一個休息時間; 在銷毀之后的陳述,但是你只發現了第一個副本,但如果這就是你將擁有的所有,那么這將是一個不錯的小優化。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.