我有一个需要删除/过滤重复项的对象数组。我打算只覆盖 Object 元素上的 equals 和 hachCode,然后将它们放在 Set 中……但我认为我至少应该轮询 stackoverflow 以查看是否有其他方法,也许是其他 API 的一些聪明方法?
9 回答
我在网上找到了这个
这里有两种方法可以让您删除 ArrayList 中的重复项。removeDuplicate 不维护顺序,而 removeDuplicateWithOrder 以一些性能开销维护顺序。
removeDuplicate 方法:
/** List order not maintained **/ public static void removeDuplicate(ArrayList arlList) { HashSet h = new HashSet(arlList); arlList.clear(); arlList.addAll(h); }
removeDuplicateWithOrder 方法:
/** List order maintained **/ public static void removeDuplicateWithOrder(ArrayList arlList) { Set set = new HashSet(); List newList = new ArrayList(); for (Iterator iter = arlList.iterator(); iter.hasNext();) { Object element = iter.next(); if (set.add(element)) newList.add(element); } arlList.clear(); arlList.addAll(newList); }
覆盖equals
和hashCode
创建一个集合也是我的第一个想法。无论如何,在您的继承层次结构中拥有这些方法的一些覆盖版本是一种很好的做法。
我认为如果你使用 aLinkedHashSet
你甚至会保留独特元素的顺序......
基本上,您需要一个LinkedHashSet<T>
支持List<T>
随机访问接口的实现。因此,这就是您需要的:
public class LinkedHashSetList<T> extends LinkedHashSet<T> implements List<T> {
// Implementations for List<T> methods here
...
}
方法的实现List<T>
将访问和操作底层的LinkedHashSet<T>
. 诀窍是在尝试通过 add 方法添加重复项时让此类行为正确List<T>
(抛出异常或在不同的索引处重新添加项目将是选项:您可以选择其中之一或使其用户可配置班上)。
使用 List distinctList
记录第一次iterator
偶然发现的元素,返回 distinctList 作为列表删除所有重复项
private List removeDups(List list) {
Set tempSet = new HashSet();
List distinctList = new ArrayList();
for(Iterator it = list.iterator(); it.hasNext();) {
Object next = it.next();
if(tempSet.add(next)) {
distinctList.add(next);
}
}
return distinctList;
}
我想重申 Jason 在评论中提出的观点:
为什么要把自己放在那个时候呢?
为什么将数组用于根本不应该包含重复项的数据结构?
始终使用 aSet
或 a SortedSet
(当元素也具有自然顺序时)来保存元素。如果您需要保留插入顺序,则可以使用LinkedHashSet
已指出的 。
必须对某些数据结构进行后处理通常暗示您应该选择不同的开始。
当然,原来的帖子引出了一个问题,“你是如何得到那个数组(可能包含重复的条目)的?”
您是否需要将数组(带有重复项)用于其他目的,或者您可以从一开始就简单地使用 Set 吗?
或者,如果您需要知道每个值的出现次数,您可以使用 aMap<CustomObject, Integer>
来跟踪计数。此外,Multimap 类的Google Collections定义也可能有用。
ASet
绝对是你最好的选择。从数组中删除东西(不创建新数组)的唯一方法是将它们清空,然后你会在以后进行大量的空检查。
从一般编程标准来看,您总是可以双重枚举集合,然后比较源和目标。
如果你的内部枚举总是在源之后开始一个条目,它是相当有效的(伪代码遵循)
foreach ( array as source )
{
// keep track where we are in the array
place++;
// loop the array starting at the entry AFTER the current one we are comparing to
for ( i=place+1; i < max(array); i++ )
{
if ( source === array[place] )
{
destroy(array[i]);
}
}
}
可以说,您可以添加一个休息时间;销毁后的语句,但您只发现第一个重复项,但如果这就是您将拥有的全部,那么这将是一个不错的小优化。