Java : Dirty Check for ArrayList?

838 views Asked by At

How can I perform a dirty check on an ArrayList in Java?

I have an object

Animal
{
    String animalName;
    String animalType;
    String animalPlace
}

I have two lists:

List<Animal> animalList1 = new ArrayList<Animal>();
List<Animal> animalList2 = new ArrayList<Animal>();

In the first list, I have the values:

[0][lion,Carnivorous,Africa]
[1][tiger,Carnivorous,Zambia]
[2][Goat,Herbivorous,Zimbabwe]

In the second list, I have the values:

[0][lion,Carnivorous,Africa]
[1][tiger,Carnivorous,Zambia]
[2][Goat,Herbivorous,Norway]

In the second list, the animalPlace for the element at index 2 has changed from Zimbabwe to Norway. How do I compare the two list values and the values which have changed put that object in a separate list?

List<Animal> animalList3 = new ArrayList<Animal>();

[0] [Goat,Herbivorous,Norway]

I know the traditional way of doing it by comparing the list using a for loop:

for (int i = 0; i < list1.size(); i++) 
{
  for (int j = i+1; j < list2.size(); j++) 
  {
    // compare list1 and list2 values
  }
}

Is there any faster and/or better way?

2

There are 2 answers

1
AJNeufeld On

The List#removeAll() method is your friend.

Implement equals() and hashCode() for Animal, and then:

List<Animal> animalList3 = new ArrayList<Animal>(animalList2);
animalList3.removeAll(animalList1);
4
azro On

You can do it this way : iterate over second list and keep only the ones that are also in first list BUT which are not equals : they have been modified (type or place, name is same)

List<Animal> res = animalList2.stream()
            .filter(a -> animalList1.stream()
                        .anyMatch(b -> !b.equals(a) && b.animalName.equals(a.animalName)))
            .collect(Collectors.toList());

With :

List<Animal> animalList1 = new ArrayList<Animal>();
animalList1.add(new Animal("lion", "Carnivorous", "Africa"));
animalList1.add(new Animal("tiger", "Carnivorous", "Zambia"));
animalList1.add(new Animal("Goat", "Herbivorous", "Zimbabwe"));
animalList1.add(new Animal("Donkey", "Herbivorous", "Zimbabwe"));

List<Animal> animalList2 = new ArrayList<Animal>();
animalList2.add(new Animal("lion", "Carnivorous", "Africa"));  //not new but no modif   X
animalList2.add(new Animal("tiger", "Carnivorous", "Zambia")); //not new but no modif   X
animalList2.add(new Animal("Goat", "Herbivorous", "Norway"));  //not new and modif      V
animalList2.add(new Animal("Horse", "Herbivorous", "Norway")); //new                    X

You'll get only [Goat,Herbivorous,Norway] at the end, the only one which is an update from first list to second


And you need an equals() like this :

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Animal animal = (Animal) o;
    return animalName.equals(animal.animalName) && animalType.equals(animal.animalType) && animalPlace.equals(animal.animalPlace);
}