Apex: Tailoring Equals And HashCode Methods For Custom Classes To Suit Your Requirements

Opening Statement

equals() method: This function assists in determining whether two instances of a class are identical or not. In Apex, every class is accompanied by a base Object class that possesses a default equals() method. This default method evaluates whether two objects share the same memory addresses. However, there are instances where comparison based on content or state rather than identity is preferred. This is when customization of the equals() method becomes relevant for our custom classes.

hashCode() method: This method furnishes a unique integer, referred to as a hash code, for an object. Hash codes are extremely beneficial for collections like Set and Map, utilizing them to efficiently arrange and locate objects. The hash code aids in determining the object’s storage location, simplifying retrieval at a later stage. Similar to the equals() method, the default hashCode() method in the Object class leverages the object’s memory address to generate the hash code. This aligns well with the default equals() behavior.

Establishing Equivalence Using  equals()

By overriding equals(), you specify the criteria for considering two instances of your class as equivalent. Typically, this criterion is reliant on the values held within specific fields. For instance, in a Person class, you might deem two Person objects as equal if they share the same ID number or possess identical combinations of name and date of birth. The critical aspect is to ensure the consistency and logical coherence of your equals() method, aligning it with the pertinent business rules or use cases.

The Significance of hashCode()Uniformity

The agreement between equals() and hashCode() states that if two objects are deemed equal by the equals() method, they should yield the same hash code. This alignment is critical for the proper functioning of hash-based collections. Violating this agreement can result in unpredictable behavior within collections. For instance, it might cause apparent ‘duplicates’ within a Set, or an inability to retrieve an object from a Map despite its presence.

Illustration of Overriding Equals and HashCode

public with sharing class EqualCheck {

    private String anyProperty;

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

Now, let’s experiment! If we try to include two instances of EqualCheck into a Set, what do you think the resulting size will be – 1 or 2? Take a guess, and let’s unveil the outcome!

Execute the following anonymous Apex:

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

System.debug(uniqueEqualChecks.size());

The size is 2.

Do you know the reason behind this?

By default, two instances of a custom class are perceived as distinct unless you customize the equals() and hashCode() methods within your class. These methods play a crucial role for Sets in determining whether two objects are identical (i.e., duplicates) or not.

Let’s proceed to 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;
    }
}

Now, upon re-executing the anonymous Apex, the resulting size is 1.

This article highlights the significance of customizing the equals() and hashCode() methods within Apex custom classes. The equals() method serves to ascertain the similarity between two instances of a class, whereas the hashCode() method creates a distinct integer for streamlined organization within collections such as Set and Map. Additionally, we delve into the correlation between these methods and present an example illustrating their overriding, ensuring consistent and logical behavior within your custom classes.