簡體   English   中英

在Java中刪除數組中重復項的最佳方法是什么?

[英]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維護訂單的順序,其中包含一些性能開銷。

  1. removeDuplicate方法:

     /** List order not maintained **/ public static void removeDuplicate(ArrayList arlList) { HashSet h = new HashSet(arlList); arlList.clear(); arlList.addAll(h); } 
  2. 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); } 

覆蓋equalshashCode並創建一個集合也是我的第一個想法。 在繼承層次結構中,無論如何都要對這些方法進行一些重寫,這是一種很好的做法。

認為如果你使用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可由班級用戶配置)。

我想重申傑森在評論中提出的觀點:

為什么要把自己放在那一點上?

為什么要將數組用於不應該重復的數據結構?

使用SetSortedSet (當元素具有自然順序時)始終保持元素。 如果您需要保持插入順序,那么您可以使用已指出的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.

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