2012-09-03 49 views
31

我們如何通過番石榴api幫助刪除列表中的重複項?使用番石榴從列表中刪除重複

目前我跟隨這名:

private List<T> removeDuplicate(List<T> list){ 
return new ArrayList<T>(new LinkedHashSet<T>(list)); 
} 
+5

你爲什麼喜歡去番石榴,如果基本的設置做到這一點? –

+0

並以這種簡潔的方式, – Thilo

+0

@PriyankDoshi爲什麼不只是'HashSet'? – oldrinb

回答

63

也許最有效的方法是ImmutableSet.copyOf(list).asList(),它消除了重複並保留了迭代次序。

(但隨着LinkedHashSet你的實現是幾乎一樣有效,並且不會扔了對空,在你實際上在您的收藏想空萬一。)

+3

_If_你沒有空元素;) – Xaerxess

+1

是的,但95%的集合沒有。 –

0

您可以嘗試番石榴的多集API刪除duplicates.Just添加列表做了設置和使用計數方法。

MultiSet

1

如果你想不惜任何代價使用番石榴,你可以做

return new ArrayList<T>(HashMultiSet<T>.create(list).elementSet()) 
1

我真的不建議使用(Linked)HashMultiSet做任務,就像OP上述與ArrayList(Linked)HashSet通常做對普通的Java程序員來說它的可讀性較差,(可能)效率較低。

相反,至少使用靜態工廠構造像newArrayListnewLinkedHashSet,以避免所有這些<T> S:

private static <T> List<T> removeDuplicate(final List<T> list) { 
    return Lists.newArrayList(Sets.newLinkedHashSet(list)); 
} 

但是,你可以做更多的「番石榴路」 - 通過avoiding nulls和使用immutable collections

所以,如果您的收藏不能有null元素,我建議使用的immutable set代替mutable and less efficient one

private static <T> List<T> removeDuplicate(final List<T> list) { 
    return Lists.newArrayList(ImmutableSet.copyOf(list)); 
} 

它仍然複製對象的兩倍,因此考慮是完全不可改變的,改變方法簽名返回ImmutableList

private static <T> ImmutableList<T> removeDuplicate(final List<T> list) { 
    return ImmutableSet.copyOf(list).asList(); 
} 

這種方式只有一個參與複製,因爲ImmutableCollection.asList()返回一個視圖。

12

我愛Louis' answer爲它的簡單性(因爲這是唯一不需要2次迭代的答案),但不幸的是,在現實世界中,你經常會遇到null確實發生的情況。這裏有一個稍微長一點空安全版本:

ImmutableSet.copyOf(
    Iterables.filter(
     list, Predicates.not(Predicates.isNull()))).asList(); 

或者,用靜態導入:

copyOf(filter(list, not(isNull()))).asList(); 

當然,你需要知道的事實,即所有null值將從列表中消失。

+3

有一個'Predicates.notNull()'謂詞已經可用。所以最終的結果是'copyOf(filter(list,notNull())。asList();'。 – Jonas

+0

@Jonas true。但當時我寫這個方法不存在 –

7

與普通謂語

class DuplicateRemover<T> implements Predicate<T> { 

    private final Set<T> set = new HashSet<>(); 

    @Override 
    public boolean apply(T input) { 

     boolean flag = set.contains(input); 

     if (!flag) { 
      set.add(input); 
     } 

     return !flag; 
    } 

} 
+1

請注意,只有實際添加元素時,set.add纔會返回true,因此不需要調用set.contains。 – Trejkaz