34

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

目前我正在关注这个:

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

6 回答 6

69

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

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

于 2012-09-03T13:04:43.873 回答
12

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

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

或者,使用静态导入:

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

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

于 2012-09-03T15:31:52.500 回答
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;
    }

}
于 2015-05-14T02:24:01.117 回答
1

如果您想以任何价格使用番石榴,您都可以

return new ArrayList<T>(HashMultiSet<T>.create(list).elementSet())
于 2012-09-03T04:57:22.283 回答
1

我真的不建议使用(Linked)HashMultiSetto do 任务,这些任务通常由上面提到ArrayList(Linked)HashSetOP 完成 - 它对于普通 Java 程序员来说可读性较差,并且(可能)效率较低。

相反,至少使用像newArrayListand这样的静态工厂构造函数newLinkedHashSet来避免所有这些<T>

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

但是,您可以通过更“番石榴方式”来做到这一点 - 通过避免空值和使用不可变集合

因此,如果您的集合不能包含 null 元素,我建议使用不可变集合而不是可变且效率较低的集合:

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

它仍在复制对象两次,因此请考虑完全不可变并将方法签名更改为 return ImmutableList

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

这种方式只涉及一次复制,因为ImmutableCollection.asList()返回一个视图。

于 2012-09-03T11:31:08.963 回答
0

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

多集

于 2012-09-03T04:48:49.730 回答