Java: Automatic equals() and hashCode()

Viewed 13469

Implementing equals() and hashCode() for simple data POJOs is cluttering my code and maintaining is tedious.

What are the libraries handling this automatically?
I prefer bytecode instrumentation over AOP approach due to performance reasons.

Update: The topic of the necessity of implementing equals() and hashCode() has been discussed, here's my point:

Isn't it better to have it done right upfront with minimal effort rather than digging in the code, adding hC/eq when it comes to it?

Edit 2022: I have switched to Kotlin. Kotlin takes care of most of Java's boilerplate, see this page for the case of equals(): https://tedblob.com/kotlin-data-class/

6 Answers

Objects.hashCode & Objects.hash

While not the panacea you requested, writing the hashCode override is a bit easier now as of Java 7 and later.

As of Java 7, the Objects class offers a couple of utility methods for generating hash code values.

See my Answer on a related Question for more discussion.

Single member, not tolerating a NULL

@Override
public int hashCode() {
    return this.member.hashCode() ;  // Throws NullPointerException if member variable is null.
}

Single member, tolerating a NULL

@Override
public int hashCode() {
    return Objects.hashCode( this.member ) ;  // Returns zero (0) if `this.member` is NULL, rather than throwing exception.
}

Multi-member

@Override
public int hashCode() {
    return Objects.hash( this.memberA , this.memberB , this.memberC  ) ;  // Hashes the result of all the passed objects’ individual hash codes.  
}

Records

Java 16 gained a new feature, records.

If the main purpose of your class is to communicate data transparently and immutably, write the class as a record.

By default, you need do nothing more than declare the member fields. The compiler implicitly creates the constructor, getters, equals & hashCode, and toString.

record Person ( String givenName , String surname ) {}

record Point ( int x , int y ) {}

record User ( UUID id, String name ) {}

The default behavior of a record’s equals & hashCode is to consider each and every member field. You can override to provide your own logic.

I highly recommend reading the Java JEP linked above. You’ll learn that the purpose of the record feature is not a reduction in boilerplate. Less code is a nice extra benefit. But if you choose record only for less typing, you’ll likely be abusing the feature. Such abuse may confuse people reading your code, and may lead to other problems.

Related