groovy

How to override method equal and hashcode (Groovy)


I created Person below:

public class Person {
    private String sCode;
    private String sDate;

    Person(String sCode, String sDate) {
        this.sCode = sCode;
        this.sDate = sDate;
    }// Constructor and other methods...

    @Override
    boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person oPerson = (Person) obj;
        return oPerson.sCode == this.sCode && oPerson.sDate == this.sDate;
    }

    @Override
    public int hashCode() {
        return Objects.hash(this.sCode, this.sDate);
    }
}

I want to store Person object in HashSet (personSet):

HashSet<Person> personSet = new HashSet<>();
Person person1 = new Person("Aman", "2021-01-01");
Person person2 = new Person("Aman", "2021-01-01");
personSet.add(person1);
personSet.add(person2);
System.out.println(personSet.size());  //Expected size to be "1"

But I got error Caught: java.lang.StackOverflowError below:

Caught: java.lang.StackOverflowError
java.lang.StackOverflowError
    at Person.equals(Person.groovy:12)

Could someone please suggest me why does my code throw this error?


Solution

  • In Groovy, == calls .equals. So the line if (this == obj) return true creates the endless loop causing the stack-overflow exception. If you want to know if two references are the same, use .is (or ===), e.g. if (this.is(obj)) return true.

    This said, there is hardly a reason for writing your own "equals and hash-code" (or worse, let your IDE generate them) with Groovy. There is EqualsAndHashCode, that does what you need with a single line of code and very likely doing the very best version of it.