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


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 defaultequals()
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 theequals()
method, the defaulthashCode()
method in the Object class uses the object's memory address to create the hash code. This works well with the defaultequals()
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.
Subscribe to my newsletter
Read articles from Nagendra Singh directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Nagendra Singh
Nagendra Singh
Allow me to introduce myself, the Salesforce Technical Architect who's got more game than a seasoned poker player! With a decade of experience under my belt, I've been designing tailor-made solutions that drive business growth like a rocket launching into space. ๐ When it comes to programming languages like JavaScript and Python, I wield them like a skilled chef with a set of knives, slicing and dicing my way to seamless integrations and robust applications. ๐ฝ๏ธ As a fervent advocate for automation, I've whipped up efficient DevOps pipelines with Jenkins, and even crafted a deployment app using AngularJS that's as sleek as a luxury sports car. ๐๏ธ Not one to rest on my laurels, I keep my finger on the pulse of industry trends, share my wisdom on technical blogs, and actively participate in the Salesforce Stackexchange community. In fact, this year I've climbed my way to the top 3% of the rankings! ๐งโโ๏ธ So, here's to me โ your humor-loving, ultra-professional Salesforce Technical Architect! ๐ฅณ