4

I have overrided the equals method of a java object. (actually the objects in kotlin but its easily understood im just overriding the equals method). but now inorder to maintain the equals contract i should also override the hashcode method. but im not sure how to put in a implementation for hashcode that suits the equals method. here is what i have so far:

    data class AddressModel(
        var id_address: Int = 0,
        var id_country: Int = 0,
) {

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other !is AddressModel)
            return false
        else {
            if (other.id_address == this.id_address)
                return true
        }
        return false
    }
}

compiler highly suggest i override hashCode method. but i dont understand what to implement. in the equals override i simply want to check if addressModel has same Id as another, if it does ,then i assume its equal.

this is what i have so far:

override fun hashCode(): Int {
        return Objects.hash(id_address, id_country);
    }

but i think this is better:

override fun hashCode(): Int {
            return Objects.hash(id_address); //base hash off same as equals the id_address
        }

this is recommended way i read but what does it mean ? if i added more class fields would i need to add more fields to the Objects.hash method also ? i would prefer the old skool way to do it as this call requires android api 19 and i support lower (api 16).

to be clear, i understand that If i don't override hashcode along with equals then every instance, e.g. "new AddressModel(707, 867)", will have a different hashcode. and then the HashMap for example will think these objects are distinct and not equal to replace them when calculating the hash for storage. but i just dont know what to put in the hashCode implementation. you can show me in either kotlin or java its ok.

update: would this be sufficient:

override fun hashCode(): Int { return id_address.hashCode() }
j2emanue
  • 60,549
  • 65
  • 286
  • 456
  • 1
    As per the accepted [answer](https://stackoverflow.com/questions/17027777/relationship-between-hashcode-and-equals-method-in-java) *If you have two objects which are .equals(), but have different hash codes, you lose!* – Scary Wombat Oct 17 '18 at 04:54
  • these links myt be useful : https://stackoverflow.com/questions/20536890/overriding-equals-and-hashcode-methods-in-java https://www.geeksforgeeks.org/override-equalsobject-hashcode-method/ https://crunchify.com/how-to-override-equals-and-hashcode-method-in-java/ – Akhil S Kamath Oct 17 '18 at 04:56
  • i already stated the same thing. im asking can you help me to know how to implement hashCode() – j2emanue Oct 17 '18 at 04:56
  • so can i do: override fun hashCode(): Int { return id_address.hashCode() – j2emanue Oct 17 '18 at 04:59
  • Note: You can simplify that 'equals' method to a one-liner: override fun equals(other: Any?) = this === other || (other is AddressModel && id_address == other.id_address). – Some Guy Jan 24 '19 at 19:22

2 Answers2

10

Since, your #equals() depends only on id_address, it should be used in hash code calculations. I would prefer:

override fun hashCode() = Objects.hash(id_address)
Prashant
  • 4,775
  • 3
  • 28
  • 47
  • Objects.hash is not available to me as im supporting older devices. can you show me how to do it the older way ? can i just do override fun hashCode() = id_address.hashCode() and then i'd also have to know what to do if id_address is null – j2emanue Oct 17 '18 at 05:07
  • 1
    override fun hashCode() = id_address , i did it this way. and i made id_address default to zero. thanks for the help. – j2emanue Oct 17 '18 at 06:47
  • You can also use the elvis operator to support nulls in the hashcode: override fun hashCode() = id_address ?: -12345 // or any other arbitrary value, preferably not zero since that will produce hash collisions if id_address is often zero. – Some Guy Jan 24 '19 at 19:28
  • 2
    Note that in recent versions of Kotlin (1.3 or later, I think), hashCode can be called even on null objects. See [here](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/hash-code.html) for details. So in that case, there is no need for an elvis operator. – Some Guy Jan 24 '19 at 19:30
  • Nice one @SomeGuy – Prashant Jan 25 '19 at 06:19
2

Sample POJO class (dataVO) overrides hashcode and equals, @Data : Lombok

Useful Links :

https://www.geeksforgeeks.org/override-equalsobject-hashcode-method/

Why do I need to override the equals and hashCode methods in Java?

https://crunchify.com/how-to-override-equals-and-hashcode-method-in-java/

 @Data

    public class dataVO implements Serializable {

    private static final long serialVersionUID = 1L;
    private int id;
    private String name;

   public String toString(){ 
          return "name:"+name;  
    }  
  @Override
    public boolean equals(Object obj) {
       if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
     if (your logic) {
        return true; 
     }
     else {
       return false;
     }
   }

    @Override
    public int hashCode() {
        return id;
    }
}
Akhil S Kamath
  • 1,012
  • 13
  • 23