使用 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 程序员来说可读性较差并且(可能)效率较低。
相反,至少使用像newArrayList
和newLinkedHashSet
这样的静态工厂构造函数来避免所有这些<T>
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 从列表中删除重复项的主要内容,如果未能解决你的问题,请参考以下文章