【问题标题】:Removing common elements from two lists of custom objects从两个自定义对象列表中删除公共元素
【发布时间】:2019-05-10 19:31:07
【问题描述】:

在下面的代码中,我有两个图像对象列表(fromTagList 和 fromImageList)。图像类有一个属性图像 URL。两个列表中有共同的对象。

我的目标是根据它们的 URL 属性检测这些常见元素并将它们从两个列表中删除,以便两个列表将包含不同的元素,然后我会将两个列表合并为一个列表,以便合并后的列表将包含不同的对象。问题是我使用的以下方法没有删除所有常见元素,因为我认为这样会跳过一些索引。

for (int i = 0; i < fromTagList.size(); i++) {
    for (int k = 0; k < fromImageList.size(); k++) {
        if (fromTagList.get(i).getImageURL().equals(fromImageList.get(k).getImageURL())) {
            fromTagList.remove(i);
            fromImageList.remove(k);
        }
    }
}

【问题讨论】:

    标签: java android list object


    【解决方案1】:

    .remove(index) 带走元素,这使列表更短,但您的索引不考虑这一点,并继续添加 1 但实际上跨过 2 个元素(+1 和已删除的元素)。

    这适用于重复元素的内联删除,但当一个列表包含重复元素时它会失败。它适用于列表中没有重复元素的情况,因为我向后遍历元素。请注意标记为继续。

    //the new ArrayList is needed so remove is supported
        List<String> fromTagList = new ArrayList(Arrays.asList(new String[] {"a", "b", "c", "1", "2", "3"}));
        List<String> fromImageList = new ArrayList(Arrays.asList(new String[] {"b", "b", "c", "d", "2", "3", "4"}));
    
        outer: for (int i = fromTagList.size()- 1; i >= 0; i--) {
            for (int k = fromImageList.size() - 1; k >= 0; k--) {
            System.out.println("i: " + i + " k: " + k);
            if (fromTagList.get(i).equals(fromImageList.get(k))) {
                fromTagList.remove(i);
                fromImageList.remove(k);
                continue outer;
            }
            }
        }
    
        System.out.println("fromTag  : " + fromTagList);
        System.out.println("fromImage: " + fromImageList);
    

    如果您想支持具有重复元素的列表,我认为您不能随时删除。我建议添加到要删除的新元素列表中。

    【讨论】:

    • 是的,这正是正在发生的事情,但是您有什么解决办法吗,谢谢
    • 有效!非常感谢,但仍然有疑问为什么使用 int i = fromTagList.size()- 1;而不是 int i =0 有什么区别?
    【解决方案2】:

    我会创建一个字典。遍历每个列表(单独)。对于每个对象,将其推送到字典中,键是其 URL。这样,任何具有相同 URL 的对象都将在字典中显示为一个键值对。将所有内容添加到字典后,将字典转换为列表。

    【讨论】:

      【解决方案3】:

      是的,您确实有索引问题,问题是当您从列表中删除某些内容时,例如在位置 i=10,位置 11 的元素将位于第 10 位,而 i 将位于第 11 位,因此您将错过这个元素,第二个问题是当你从 k 索引器的第二个列表中删除时,你应该中断,不处理所有其余元素(除非找到的元素不重复),所以这是我的答案,之后对我有用尝试您的代码:

      for (int i = 0; i < fromTagList.size(); i++) {
                  for (int k = 0; k < fromImageList.size(); k++) {
                      if (fromTagList.get(i).getImageURL().equals(fromImageList.get(k).getImageURL())) {
                          fromTagList.remove(i);
                          fromImageList.remove(k);
                          i--;
                          //break; this is optional
                      }
                  }
              }
      

      【讨论】:

      • 谢谢你的回答,但是如果i=0,i--会出问题!
      • 然后测试它是否为 0 并且不更新,否则只需使用 i-- 更新它。
      【解决方案4】:

      当您需要维护 uniq 元素时,请考虑使用 Set。 java中的set接口专门用于处理uniq元素。您可以按照以下方法将列表转换为集合:

      覆盖图像对象的equals和hashcode方法(仅使用url属性作为相等和hascode的条件)。现在将两个列表添加到集合中。将集合转换回列表,瞧! 示例:

       class ImageObj {
      
          String url;
          //rest of the stuff
      
          @Override
          public boolean equals(Object o){
          ImageObj that = (ImageObj)o;
          return that.url.equals(this.url);
          }
          @Override
          public int hascode(){
          return Objects.hascode(this.url);
          }
          }
          }
      

      那么——

      Set<ImageObj> set= new HashSet<ImageObj>(fromTagList);
      set.addAll(fromImageList);
      
      List<ImageObj> list = new ArrayList<ImageObj>(set);
      

      这是包含所有唯一对象的最终列表。

      【讨论】:

      • 谢谢您的回答,是这样从两个列表中删除了共同元素吗?
      • 是的,此方法将从两个列表中删除重复项。试试看,如果遇到任何问题,请告诉我。每当您需要一组 uniq 元素时,请使用 set。如果成功的话给我一个upvote。干杯!! :-)
      • 我试了你的代码还是不行,公共元素没有去掉,你上面写的方法hascode()报错所以我改成hashCode()
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-04
      • 1970-01-01
      • 2013-05-17
      • 1970-01-01
      • 1970-01-01
      • 2016-12-22
      相关资源
      最近更新 更多