【问题标题】:Remove duplicates from List using Guava使用 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 是正确的选择,因为它将保留元素顺序。

标签: java list generics arraylist guava


【解决方案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 程序员来说可读性较差并且(可能)效率较低。

    相反,至少使用像newArrayList 和newLinkedHashSet 这样的静态工厂构造函数来避免所有这些&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

      【讨论】:

        猜你喜欢
        • 2016-04-18
        • 2014-09-30
        • 2011-01-13
        • 2021-04-02
        • 2016-01-28
        相关资源
        最近更新 更多