Apex: Customizing Equals and HashCode Methods for Your Needs in Custom Classes

Apex: Customizing Equals and HashCode Methods for Your Needs in Custom Classes

ยท

3 min read

Introduction

  • equals() method: This method helps us figure out if two instances of a class are the same or not. In Apex, all classes come with a basic Object class that already has a default equals() method. This default method checks if two objects are the same by comparing their memory addresses. But sometimes, we might want to compare objects based on their content or state instead of their identity. That's when we can customize the equals() method for our custom classes.

  • hashCode() method: This method gives us a unique integer called a hash code for an object. Hash codes are super useful for collections like Set and Map, which use them to efficiently organize and find objects. The hash code helps figure out where to store the object, making it easy to find later. Just like with the equals() method, the default hashCode() method in the Object class uses the object's memory address to create the hash code. This works well with the default equals() behaviour.

Defining Equality with equals()

When you override equals(), you define what it means for two instances of your class to be considered equal. This is usually based on the values of certain fields. For instance, if you have a Person class, you might decide that two Person objects are equal if they have the same ID number or the same combination of name and date of birth. The key here is to ensure that your equals() method is consistent and logical according to the business rules or use case you are dealing with.

The Importance of hashCode() Consistency

The contract between equals() and hashCode() is such that if two objects are considered equal according to the equals() method, then they must also return the same hash code. This consistency is crucial for the correct operation of hash-based collections. If this contract is violated, it can lead to unpredictable behaviour in collections. For example, you might end up with 'duplicate' entries in a Set or you might fail to retrieve an object from a Map even though it's present.

Example of overriding Equals and HashCode

public with sharing class EqualCheck {

    private String anyProperty;

    public EqualCheck(String anyProperty){
        this.anyProperty = anyProperty;
    }
}

Now! If we attempt to add two instances of EqualCheck into a Set, what do you think the size will be - 1 or 2? Take a wild guess and let's find out!

Run the below anonymous apex:

Set<EqualCheck> uniqueEqualChecks = new Set<EqualCheck>();
uniqueEqualChecks.add(new EqualCheck('123'));
uniqueEqualChecks.add(new EqualCheck('123'));

System.debug(uniqueEqualChecks.size());

Size is 2.

Do you know why?

By default, two instances of a custom class are considered different unless you override the equals() and hashCode() methods in your class. These methods are used by the Set to determine if two objects are the same (i.e., duplicates) or not.

Now let's override equals() and hashCode()

public with sharing class EqualCheck {

    private String anyProperty;

    public EqualCheck(String anyProperty){
        this.anyProperty = anyProperty;
    }

    public Boolean equals(Object thatObject) {
        if (this === thatObject) return true;
        if (!(thatObject instanceof EqualCheck)) return false;
        EqualCheck that = (EqualCheck) thatObject;
        return (((anyProperty != null) && anyProperty.equals(that.anyProperty)) || ((that.anyProperty != null) && that.anyProperty.equals(anyProperty)) || (anyProperty == that.anyProperty));
    }

    public override Integer hashCode() {
        Integer result = anyProperty != null ? System.hashCode(anyProperty) : 0;
        return result;
    }
}

And now let's rerun the anonymous apex, the size is 1.

In this article, we discuss the importance of overriding the equals() and hashCode() methods in Apex custom classes. The equals() method is used to determine if two instances of a class are the same, while the hashCode() method generates a unique integer for efficient organization in collections like Set and Map. We also explore the relationship between these methods and provide an example of how to override them for consistent and logical behaviour in your custom classes.

Did you find this article valuable?

Support Nagendra Singh by becoming a sponsor. Any amount is appreciated!

ย