比较两个列表并获得差异

新手上路,请多包涵

我有两个列表。它们包含不同类型的对象,但两种类型都包含 id 和 name,而 id 是我比较的对象。列表一是从数据库中获取的,列表二是从前端发送的。

我需要做的是遍历它们并找到新添加的列表项和删除的列表项。

我能够做到,但问题是它看起来很难看。

假设我有一个名为 NameDTO 的对象,它可以有 ID 和名称。列表二充满了那种类型的对象。

我就是这样做的:

 final ArrayList<NamedDTO> added = new ArrayList<>();
final ArrayList<NamedDTO> removed = new ArrayList<>();

for(NamedDTO listTwoObject : listTwo) {
   boolean contained = false;
   for(SomeObject listOneObject : listOne) {
       if(listTwoObject.getId().equals(listOneObject.getId()) {
           contained = true;
       }
   }
   if(!contained) {
      added.add(listTwoObject);
   }
}

for(SomeObject listOneObject : listOne) {
   boolean contained = false;
   for(NamedDTO listTwoObject : listTwo) {
       if(listTwoObject.getId().equals(listOneObject.getId()) {
           contained = true;
       }
   }
   if(!contained) {
      removed.add(new NamedDTO(listOneObject.getId(), listOneObject.getName()));
  }
}

这行得通,我已经测试过了。有更好的解决方案吗?我正在考虑使用 Sets 以便我可以比较它们,这有缺点吗?

原文由 mirzak 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 480
2 个回答

如果我理解正确,这是示例场景:

  • listOne [datab] 项目: [A, B, C, D]
  • listTwo [前]项: [B, C, D, E, F]

你需要得到的效果是:

  • 添加: [E, F]
  • 删除: [A]

首先,我会使用某种类型适配器或从一个通用类扩展不同类型和 override equals 方法,这样你就可以通过 idname

其次,这是对集的非常简单的操作(您可以使用集,但列表也可以)。我推荐使用一个库: https ://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/CollectionUtils.html

现在基本上:

  • 添加的是 listTwo - listOne
  • 删除的是 listOne - listTwo

并使用java代码:

  • 添加: CollectionUtils.removeAll(listTwo, listOne)
  • 删除: CollectionUtils.removeAll(listOne, listTwo)

否则,所有实现 CollectionJava 文档)的集合也有 removeAll 方法,您可以使用它。

原文由 Atais 发布,翻译遵循 CC BY-SA 3.0 许可协议

我提出使用 java 8 流的解决方案:

     ArrayList<ObjOne> list = new ArrayList<>(Arrays.asList(new ObjOne("1","1"),new ObjOne("3","3"),new ObjOne("2","2")));
    ArrayList<ObjTwo> list2 = new ArrayList<>(Arrays.asList(new ObjTwo("1","1"),new ObjTwo("3","3"),new ObjTwo("4","4")));

    List<ObjOne> removed = list.stream().filter(o1 -> list2.stream().noneMatch(o2 -> o2.getId().equals(o1.getId())))
            .collect(Collectors.toList());
    System.out.print("added ");
    removed.forEach(System.out::println);

    List<ObjTwo> added = list2.stream().filter(o1 -> list.stream().noneMatch(o2 -> o2.getId().equals(o1.getId())))
             .collect(Collectors.toList());

    System.out.print("removed ");
    added.forEach(System.out::println);

这基本上是您的解决方案,但使用流实现,这将使您的代码更短且更易于阅读

原文由 Kamil Banaszczyk 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题