给定一个对象列表(所有相同类型),如何确保它只包含某个属性的每个值的一个元素,即使equals()可能因为更多属性而对这些元素返回false被检查?在代码中:
private void example() {
List<SomeType> listWithDuplicates = new ArrayList<SomeType>();
/*
* create the "duplicate" objects. Note that both attributes passed to
* the constructor are used in equals(), though for the purpose of this
* question they are considered equal if the first argument was equal
*/
SomeType someObject1 = new SomeObject1("hello", "1");
SomeType someObject2 = new SomeObject1("hello", "2");
List<SomeType> listWithoutDuplicates = removeDuplicates(listWithDuplicates)
//listWithoutDuplicates should not contain someObject2
}
private List<SomeType> removeDuplicates(List<SomeType> listWithDuplicates) {
/*
* remove all but the first entry in the list where the first constructor-
* arg was the same
*/
}
答案 0 :(得分:8)
可以使用Set作为中间占位符来查找重复项,如Bozho建议的那样。这是一个示例removeDuplicates()
实现。
private List<SomeType> removeDuplicates(List<SomeType> listWithDuplicates) {
/* Set of all attributes seen so far */
Set<AttributeType> attributes = new HashSet<AttributeType>();
/* All confirmed duplicates go in here */
List duplicates = new ArrayList<SomeType>();
for(SomeType x : listWithDuplicates) {
if(attributes.contains(x.firstAttribute())) {
duplicates.add(x);
}
attributes.add(x.firstAttribute());
}
/* Clean list without any dups */
return listWithDuplicates.removeAll(duplicates);
}
答案 1 :(得分:1)
也许可以像这样使用HashMap:
private List<SomeType> removeDuplicates(List<SomeType> listWithDuplicates) {
/*
* remove all but the first entry in the list where the first constructor-
* arg was the same
*/
Iterator<SomeType> iter = listWithDuplicates.iterator();
Map<String, SomeType> map = new HashMap<String, SomeType>();
while(iter.hasnext()){
SomeType i = iter.next();
if(!map.containsKey(i.getAttribute())){
map.put(i.getAttribute(), i);
}
}
//At this point the map.values() is a collection of objects that are not duplicates.
}
答案 2 :(得分:0)
如果equals()
合适,我可以推荐一些“标准”集合类/方法。事实上,我认为你唯一的选择就是
首先检查原始列表中所有前面的元素是否有重复项,然后将每个元素复制到另一个列表中;或
从列表中删除您在之前位置发现重复的任何元素。对于列表内删除,您最好使用LinkedList
,其中删除不是那么昂贵。
在任何一种情况下,检查重复项都是O(n ^ 2)操作,唉。
如果您要进行大量此类操作,则可能需要将列表元素包装在另一个类中,该类根据您自己定义的条件返回哈希码。
答案 3 :(得分:0)
我会考虑为这样的事情实现Comparator
接口。如果您希望使用一个或两个简单的属性进行比较,那么这非常简单。
Related question: How Best to Compare Two Collections in Java and Act on Them?