2010-11-03 62 views
4

Rec對象具有稱爲tag一個成員變量這是一個String如何重複數據刪除的對象的列表?

如果我有一個ListRec s,我怎麼能根據tag成員變量取消這個列表?

我只需要確保該List只包含一個Rec每個tag值。

類似下面的,但我不知道什麼是最好的算法來跟蹤計數等:

private List<Rec> deDupe(List<Rec> recs) { 

    for(Rec rec : recs) { 

     // How to check whether rec.tag exists in another Rec in this List 
     // and delete any duplicates from the List before returning it to 
     // the calling method? 

    } 

    return recs; 

} 
+0

如果你問我怎麼從列表中刪除重複的,這已經被問過很多次;的[刪除從列表重複] http://stackoverflow.com/search?q=[java]+removing+duplicates – Qwerky 2010-11-03 14:52:58

+0

可能重複(http://stackoverflow.com/questions/2849450/remove-duplicates-from-a -list) – 2010-11-03 14:55:41

回答

6

存儲。

創建HashMap<String,Rec>。通過所有Rec對象的循環。對於每一個,如果tag已經存在,作爲一個HashMap鍵,然後比較這兩個,並決定保留哪一個。如果不是,則將其放入。

完成後,HashMap.values()方法將爲您提供所有唯一的Rec對象。

+2

如果您希望values()保留List排序,請使用LinkedHashMap。 – 2012-11-05 22:09:53

1

這變得更容易,如果Rec.equals基於其tag價值。然後,你可以寫這樣的:

private List<Rec> deDupe(List<Rec> recs) 
{ 
    List<Rec> retList = new ArrayList<Rec>(recs.size()); 
    for (Rec rec : recs) 
    { 
     if (!retList.contains(rec)) 
     { 
      retList.add(rec); 
     } 
    } 
    return retList; 
} 
+4

你不能使用Set.addAll(RECs)的? – Rich 2010-11-03 14:52:25

+0

@Rich - 我嘗試使用HashSet,但我能夠添加具有不同'tag'值的多個對象,因此該集合的唯一性似乎基於'Rec'對象的某個其他屬性,但我不確定是什麼它是。 – 2010-11-03 14:55:03

+0

@Rich:是的,那將工作(可能比我更好的提交) – 2010-11-03 14:55:29

5

試試這個:

private List<Rec> deDupe(List<Rec> recs) { 

    Set<String> tags = new HashSet<String>(); 
    List<Rec> result = new ArrayList<Rec>(); 

    for(Rec rec : recs) { 
     if(!tags.contains(rec.tags) { 
      result.add(rec); 
      tags.add(rec.tag); 
     } 
    } 

    return result; 
} 

這將檢查每個Rec針對Set的標籤。如果該集合已經包含標籤,則它是重複的,我們將其跳過。否則,我們添加Rec我們的結果和標籤添加到該集合。在HashMap<String,Rec>暫時

+0

之前,你可以把它簡單的使用Set.add的返回值:如果(tags.add(rec.tags))result.add(REC) – Tom 2010-11-03 15:26:00

+1

是。這就是'Set'用於......具有不同對象的集合。 – heez 2016-08-09 19:00:28

0

我會做到這一點與谷歌的集合。您可以使用過濾功能,與以前的記憶標籤的謂詞,並過濾掉錄音與標籤已經去過那兒。 事情是這樣的:

private Iterable<Rec> deDupe(List<Rec> recs) 
{ 
    Predicate<Rec> filterDuplicatesByTagPredicate = new FilterDuplicatesByTagPredicate(); 
    return Iterables.filter(recs, filterDuplicatesByTagPredicate); 
} 

private static class FilterDuplicatesByTagPredicate implements Predicate<Rec> 
{ 
    private Set<String> existingTags = Sets.newHashSet(); 

    @Override 
    public boolean apply(Rec input) 
    { 
     String tag = input.getTag(); 
     return existingTags.add(tag); 
    } 
} 

我稍微改變了方法,而不是返回列表的可迭代,但ofcourse你改變,如果這很重要。

+0

爲謂詞的Javadoc強烈建議針對具有謂詞其中應用()具有任何可觀察到的副作用。看到這個問題:http://stackoverflow.com/questions/4036326/google-collections-distinct-predicate/4036416#4036416 – 2010-11-03 15:00:47

+0

能否請您解釋一下爲什麼?這裏有什麼陷阱? – duduamar 2010-11-03 15:30:05

+0

副作用使代碼難以理解,特別是當他們隱藏在意想不到的地方。 「Predicate」的標準期望是它是一個固定的邏輯謂詞,賦予它的每個元素都以相同的方式進行評估。通過這個謂詞,評估標準在一次調用過濾器的過程中不斷變化。謂詞當然不可重用......再次使用它會導致它過濾掉原始列表中的每個元素。這違反了期望..一個'Map'是解決這個問題的更合適的解決方案。 – ColinD 2010-11-03 16:08:31

0

如果你不關心周圍洗牌的數據(即你的小物件的小單子),你可以這樣做:

private List<T> deDupe(List<T> thisListHasDupes){ 
    Set<T> tempSet = new HashSet<T>(); 
    for(T t:thisListHasDupes){ 
     tempSet.add(t); 
    } 
    List<T> deDupedList = new ArrayList<T>(); 
    deDupedList.addAll(tempSet); 
    return deDupedList; 
} 

記住,集implmenations會想一致和有效的等號運算符。所以,如果你有一個自定義的對象,確保這是照顧。