2012-09-03 25 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