使用 Guava 从列表中删除重复项

Posted

技术标签:

【中文标题】使用 Guava 从列表中删除重复项【英文标题】:Remove duplicates from List using Guava 【发布时间】:2012-08-27 20:23:51 【问题描述】:

我们如何在 Guava api 的帮助下从 List 中删除重复项?

目前我正在关注这个:

private List<T> removeDuplicate(List<T> list)
return new ArrayList<T>(new LinkedHashSet<T>(list));

【问题讨论】:

为什么你喜欢买番石榴,如果基本套装可以这样做? 还有如此简洁的方式 @PriyankDoshi 为什么不只是HashSet @veer :我需要维护秩序。所以用了LinkedHashSet @MohammodHossain 不,LinkedHashSet 是正确的选择,因为它将保留元素顺序。 【参考方案1】:

可能最有效的方法是ImmutableSet.copyOf(list).asList(),它消除了重复并保留了迭代顺序。

(但您使用LinkedHashSet 的实现几乎同样有效,并且不会抛出空值,万一您实际上希望集合中有空值。)

【讨论】:

如果你没有空元素 ;) 是的,但 95% 的集合没有。【参考方案2】:

我喜欢 Louis' answer 的简单性(因为它是唯一不需要 2 次完整迭代的答案),但不幸的是,在现实世界中,您经常会遇到 null 确实发生的情况。这是一个稍长的空安全版本:

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

或者,使用静态导入:

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

当然,您需要注意所有null 值将从列表中丢失。

【讨论】:

已有一个Predicates.notNull() 谓词可用。所以最终结果将是copyOf(filter(list, notNull())).asList(); @Jonas 是的。但在我写这篇文章的时候,这个方法并不存在【参考方案3】:

带有泛型谓词

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;
    


【讨论】:

请注意,set.add 仅在实际添加元素时才返回 true,因此无需调用 set.contains。【参考方案4】:

如果你想以任何价格使用番石榴

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

【讨论】:

【参考方案5】:

我真的不建议使用 (Linked)HashMultiSet 来完成通常使用 ArrayList(Linked)HashSet 完成的任务,就像上面提到的 OP - 对于普通 Java 程序员来说可读性较差并且(可能)效率较低。

相反,至少使用像newArrayListnewLinkedHashSet 这样的静态工厂构造函数来避免所有这些&lt;T&gt;s:

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

但是,您可以通过更多“番石榴方式”来做到这一点 - 通过 avoiding nulls 和使用 immutable collections。

所以如果你的集合不能有空元素,我建议使用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() 返回一个视图。

【讨论】:

【参考方案6】:

您可以尝试使用 Guava 的 MultiSet API 来删除重复项。只需添加您的列表并使用计数方法。

MultiSet

【讨论】:

以上是关于使用 Guava 从列表中删除重复项的主要内容,如果未能解决你的问题,请参考以下文章

从列表中删除重复项?

使用 Python 删除对象列表中的重复项

从 Ocaml 中的列表列表中删除重复项?

如何从我的列表中删除重复项? [复制]

如何从Java列表中删除重复项

从 Python 列表中删除重复项