Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing two lists and getting differences

I have two lists. They contain objects of different types, but both types contain id and name, and id is what I am comparing on. List one is fetched from DB, and list two is sent from frontend.

What I need to do is loop through them and find which list item is newly added and which one was deleted.

I was able to do it, but the problem is that it look ugly.

Let's say I have a object that is called NameDTO which can have id and name. List two is filled with that type of objects.

This is how I did it:

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()));
  }
}

This works, I have tested it. Are there better solutions? I was thinking of using Sets so I can compare them, Is there a downside to that ?

like image 960
mirzak Avatar asked Feb 03 '17 14:02

mirzak


People also ask

How do I compare two lists in Java and get differences?

Using the Java List API. We can create a copy of one list and then remove all the elements common with the other using the List method removeAll(): List<String> differences = new ArrayList<>(listOne); differences. removeAll(listTwo); assertEquals(2, differences.

How do you compare two lists in Python?

sort() and == operator. The list. sort() method sorts the two lists and the == operator compares the two lists item by item which means they have equal data items at equal positions. This checks if the list contains equal data item values but it does not take into account the order of elements in the list.

How do I compare two lists in Java?

Java provides a method for comparing two Array List. The ArrayList. equals() is the method used for comparing two Array List. It compares the Array lists as, both Array lists should have the same size, and all corresponding pairs of elements in the two Array lists are equal.


2 Answers

If I understand correctly, this is the example scenario:

  • listOne [datab] items: [A, B, C, D]
  • listTwo [front] items: [B, C, D, E, F]

and what you need to get as an effect is:

  • added: [E, F]
  • deleted: [A]

First thing first, I would use some type adapter or extend the different types from one common class and override the equals method so you can match them by id and name

Secondly, this is very easy operations on sets (you could use set's but list are fine too). I recommend using a library: https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/CollectionUtils.html

And now basically:

  • added is listTwo - listOne
  • deleted is listOne - listTwo

and using java code:

  • added: CollectionUtils.removeAll(listTwo, listOne)
  • deleted: CollectionUtils.removeAll(listOne, listTwo)

Otherwise, all collections implementing Collection (Java Docs) also has removeAll method, which you can use.

like image 166
Atais Avatar answered Oct 19 '22 18:10

Atais


I propose solution using java 8 streams:

    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);

This is basically your solution but implemented using streams, which will make your code shorter and easer to read

like image 20
Kamil Banaszczyk Avatar answered Oct 19 '22 19:10

Kamil Banaszczyk