比较两个列表并获取差异

2022-09-02 19:24:03

我有两个列表。它们包含不同类型的对象,但两种类型都包含id和name,id是我比较的。列表 1 从 DB 获取,列表 2 从前端发送。

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

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

假设我有一个名为NameDTO的对象,它可以有id和name。列表二填充了该类型的对象。

我是这样做到的:

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,这样我就可以比较它们,这有什么缺点吗?


答案 1

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

  • listOne [datab] 项:[A, B, C, D]
  • 列表两个 [前面] 项:[B, C, D, E, F]

你需要得到的效果是:

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

首先,我会使用一些类型适配器或从一个公共类和方法扩展不同的类型,以便您可以通过和匹配它们overrideequalsidname

其次,这是在集合上非常简单的操作(你可以使用集合,但列表也很好)。我建议使用库: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)

否则,所有集合实现(Java Docs)也都有方法,您可以使用。CollectionremoveAll


答案 2

我提出了使用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);

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


推荐