我们如何在Guava api的帮助下从 List 中删除重复项?
目前我正在关注这个:
private List<T> removeDuplicate(List<T> list){
return new ArrayList<T>(new LinkedHashSet<T>(list));
}
可能最有效的方法是ImmutableSet.copyOf(list).asList()
,它消除了重复并保留了迭代顺序。
(但是您的实现LinkedHashSet
几乎同样有效,并且不会抛出空值,万一您实际上希望集合中有空值。)
我喜欢Louis的简单答案(因为它是唯一不需要 2 次完整迭代的答案),但不幸的是,在现实世界中,您经常会遇到null
确实发生的情况。这是一个稍长的空安全版本:
ImmutableSet.copyOf(
Iterables.filter(
list, Predicates.not(Predicates.isNull()))).asList();
或者,使用静态导入:
copyOf(filter(list, not(isNull()))).asList();
当然,您需要注意所有null
值都将从列表中丢失的事实。
带有泛型谓词
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;
}
}
如果您想以任何价格使用番石榴,您都可以
return new ArrayList<T>(HashMultiSet<T>.create(list).elementSet())
我真的不建议使用(Linked)HashMultiSet
to do 任务,这些任务通常由上面提到ArrayList
的(Linked)HashSet
OP 完成 - 它对于普通 Java 程序员来说可读性较差,并且(可能)效率较低。
相反,至少使用像newArrayList
and这样的静态工厂构造函数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()
返回一个视图。
您可以尝试使用 Guava 的 MultiSet API 来删除重复项。只需添加您的列表并使用计数方法。