【问题标题】:Find objects in a list where some attributes have equal values在列表中查找某些属性具有相等值的对象
【发布时间】:2010-01-06 11:30:58
【问题描述】:

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

【问题讨论】:

    标签: java


    【解决方案1】:

    可以按照 Bozho 的建议使用 Set 作为中间占位符来查找重复项。这是一个示例 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);
    }
    

    【讨论】:

      【解决方案2】:

      也许 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.
      
      
      
        }
      

      【讨论】:

      • 可能会起作用,但我会失去列表的顺序。我将不得不检查这是否是我的问题。
      【解决方案3】:

      如果equals() 合适,我可以推荐一些“标准”集合类/方法。事实上,我认为你唯一的选择是要么

      • 首先检查原始列表中的所有前面元素是否有重复项,然后将每个元素复制到另一个列表中;或

      • 从您的列表中删除您在先前位置找到重复项的任何元素。对于列表内删除,您最好使用LinkedList,这样删除的成本并不高。

      在任何一种情况下,检查重复项都是 O(n^2) 操作,唉。


      如果您要进行大量此类操作,则可能值得将列表元素包装在另一个类中,该类会根据您自己定义的标准返回哈希码。

      【讨论】:

        【解决方案4】:

        我会考虑为类似的东西实现Comparator 接口。如果您希望使用一两个简单的属性进行比较,那将非常简单。

        Related question: How Best to Compare Two Collections in Java and Act on Them?

        【讨论】:

          猜你喜欢
          • 2016-05-01
          • 1970-01-01
          • 2013-02-13
          • 1970-01-01
          • 1970-01-01
          • 2011-10-30
          • 2023-04-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多