Search code examples
javauniqueequality

Comparing properties of objects that equal through an id


Lets assume there is a data service that returns instances of the class cat:

class Cat {
  int id;
  String name;
  int iq;
}

I want to hold the instances inside a Set<Cat> that must not hold two cats with the same id. So I need to override the equals and hashcode method to only check for the id.

My question is how can I detect if a cat inside my set requires an update when I receive a new instance from the service with the same id, but different values for name and/or iq? I cannot add the properties to equals or hashcode since then it would be possible that the Set holds instances of the same id.

Do I have to compare all the fields manually or is there another Java-typical solution for this?


Edit for clarification:

Just updating the Set with the new instance would not be enough because there is code triggered on an update. So what I want to do is:

if (set.contains(newCat)) {
  Cat current = set.get(newCat);
  if (!current.equals(newCat)) { //obviously this is not enough
    set.add(current);
    //notify EventBusses and such
  }
}

Solutions that came into my mind are:

  1. current.requiresUpdate(newCat) //basically copy of equals() with properties
  2. current.updateWith(newCat) //same as above but keeping the old instance
  3. if (!current.name.euqals(newCat.name)) //for each property
  4. only get the objects from the service that have changed. Optimal, but out of scope for me.

All of which would require somewhat redundant code which is why I was hoping there is a pattern or collection that does the work for me.
The solution can include Guava classes.


Solution

  • I think you have two distinct problems:

    • Comparing Cat objects: If two Cat objects are equal only if id, name and iq are equal, than implement the equals method accordingly.
    • Maintaining a collection of Cat objects: To maintain a collection of Cat objects in which there are no two objects with the same id, use a Map<Integer, Cat> as already suggested.

    Your code may then look something like:

    if (mapOfCats.contains(newCat.id)) {
      Cat current = mapOfCats.get(newCat.id);
      if (!current.equals(newCat)) {
        mapOfCats.put(newCat.id, newCat);
        // notify EventBusses and such
      }
    }