在列表中查找某些属性具有相等值的对象

时间:2010-01-06 11:30:58

标签: java

给定一个对象列表(所有相同类型),如何确保它只包含某个属性的每个值的一个元素,即使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
     */
}

4 个答案:

答案 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?