Equality Test

Equality, sounds easy? But, it can be hard if you didn’t take a deeper look at your objects.

OMAR ELGABRY
Jan 27, 2017 · 5 min read
Equality test can be hard if you didn’t take a deeper look at your objects — castlemedical

What’s The Problem?

Having two items; x & y, where you want to test if they are equal or not, sounds easy? but there are a lot more to consider when testing equality.

Once you can test the equality, you would be able to search for an item in a list, validate user credentials, count duplicates, and a lot more.

In Java, all the objects have a hidden secret, called equals() method.

How To Add The Equality Test?

By overriding the equals() method. All objects inherits equals() method by default.

The default implementation tests the references (memory locations) of the objects.

// do x and y (reference variables) refer to the same object?
// The == sign compares the memory locations of objects
if(x == y)

In other situations, we may consider two objects are equal even if they aren’t located in the same memory location.

String x = “hello”;
String y = “hello”;
if(x.equals(y)) // returns true

Java provides implementations for standard built-in types such as Integer, Double, String, Date, File, URL, and many others. If you’re going to use any of them, we can just use the built-in implementation of equals() method.

For example, if x and y are String values, then x.equals(y) is true if and only if they have the same length and are identical in each character position (as we’ve just seen).

If we’re going to implement our own types (user-defined), we need to override the equals() method.

Equality Test Requirements

Before getting into the details, there is an equivalence relation that must be satisfied which states that:

For any (non-null) object references x, y, and z.

  • Reflexive: x.equals(x) is true.
  • Symmetric: x.equals(y) if y.equals(x).
  • Transitive: x.equals(y) and y.equals(z), then x.equals(z).

In addition, equals() must satisfy the following properties:

  • Consistent: x.equals(y) must keep returning the same value as long as the objects are not modified.
  • Non-null: x.equals(null) must return false.

Overriding equals() Method

We are going to use the Date class as an example for demonstration purposes, but, you can use whatever data type you’ve.

There are some rules you need to follow in order to properly implement the equals() method, and here they are:

// 1. The class Date has to be final; 
// Can’t be inherited so we won’t violate the "Symmetric" relation.

public final class Date {
private final int day;
private final int month;
private final int year;
// ...

For the rule [7], …

  1. When comparing between object properties(fields):
  • If primitive, then use “==”.
  • If it’s another object, then use equals(); recursive call.
  • If an array, then compare every element in the array, or use Arrays.equals(x, y); but not x.equals(y);.

2. No need to compare between properties that depend on other properties. Because eventually, you will compare between the dependent properties.

if(this.salary != that.salary)         return false;
if(this.commission != that.commission) return false;

3. Start with comparing between properties that most likely to differ first. So, In Date class, we started by comparing the day, month, then year.

Make hashCode() method consistent with equals()

There is a method called hashCode(), which returns a hash code value for the object. It’s useful when using hash tables.

The problem is, hashing is so tied to equality, meaning, if you have changed what it means for your objects to be equal, you should also change the hash method too.

So, it’s necessary to override the hashCode() method whenever equals() method is overridden, so as to maintain the general contract for the hashCode() method, which states that equal objects must have equal hash codes.

Whenever x.equals(y), then x.hashCode() must be same as y.hashCode().

The bottom line is, If you override one, then you should override the other, and use the same set of fields that you use to compute equals() & hashCode().

Make compareTo() method consistent with equals()

If you implement Comparable in your class, and so you use compareTo() method to compare between objects, you need to override equals() method (together with hashCode()) to get consistent results.

That is, for every pair of objects x and y in any give Comparable type, it should be the case that x.equals(y) if and only if (x.compareTo(y) == 0).

Now, you might be asking, which one to use for testing equality; equals() or compareTo()?

Using equals() Vs compareTo() for testing equality

Both should be consistent (as we said), but, even if they are consistent, they aren’t interchangeable; can’t use one instead of another, Why? Because in some situations, you may get different results (see differences below).

And, If they aren’t consistent, you should mention this fact in your class documentation. The Java documentation says that:

It is strongly recommended, but not strictly required that (x.compareTo(y)==0) == (x.equals(y)). Generally speaking, any class that implements the Comparable interface and violates this condition should clearly indicate this fact.

The differences between equals() and compareTo():

  1. equals(Object b) takes any object as a parameter, but, compareTo() works on objects that implements Comparable Interface.
  2. equals() only tells you whether they’re equal or not(has a specific intent), but compareTo() gives more information on how the objects compare(less or greater than).
  3. equals() returns false if you passed null, but compareTo() should throws a NullPointerException. Note that null is not an object of any class. Therefore, getting different results when passing null doesn’t violates their consistency.

So, The bottom line is when comparing only for equality use equals(), otherwise use compareTo().

OmarElGabry's Blog

This is my freedom area. Don't underestimate it. The devil is in the detail.

OMAR ELGABRY

Written by

Software Engineer. Going to the moon 🌑. When I die, turn my blog into a story.

OmarElGabry's Blog

This is my freedom area. Don't underestimate it. The devil is in the detail.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade