How to check object equality in Java?

Java is not purely object-oriented programming language. We can use both objects and primitives for our variables. We can check easily if two primitives are same by identity operator ==. It is not as easy for objects.

==

Comparing objects with == is one of the frequented beginner’s mistakes. A beginner will check if two Strings with value “apple” are same and the answer is false. Because it doesn’t really check if objects are same but whether they point to the same memory address. How can you then check real equality of objects? Equals is the method you have to use.

Equals

 
public boolean equals(Object obj)
apple1.equals(apple2)

Checking String equality this way will give you the right answer. Purpose of equals method is to check object equality, not whether it points to the same memory address. How? It depends on how equals method is implemented. It can do really anything. So it means you have to override equals method for your own classes. Why? Because this is default equals method implementation:

public boolean equals(Object obj) {
    return (this == obj);
}

You can see that default Object’s implementation only check memory address. How can you implement equals method for your class? Basically, you have to check if all class properties are same. Let me show you an example.

public class User {
    String username;
    String firstname;
    String lastname;
}

There are 3 String variables and we have to check them all. How do we do that?

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (obj.getClass() != getClass()) return false;
    User otherUser = (User) obj;
    return otherUser.username.equals(username)
            && otherUser.firstname.equals(firstname)
            && otherUser.lastname.equals(lastname);
}

If the object is this, it cannot be anything else than the same object. If another object is null, it is certainly different because this object exists and so it cannot be null. Then we check if the object is of the same type. Please notice that first parameter of equals method is of type Object. It is because this is default method signature and the only way to override. So we need to cast another object to this and then check if all properties are same.

This will work flawlessly. But there is one more method you should override.

hashCode

public int hashCode()

You only need to override this method if your object will be used with hash-based collections as HashMap, HashSet or Hashtable.
Hashcode documentation says following:

Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided by HashMap.
The general contract of hashCode is:
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)

Simply said, without overriding this method hash collection will not recognize that it already contains the same object and insert a new one. It won’t let you insert twice the same object (because it has same generated hash) but you will be able to insert two different objects with equals comparison returning true.
How can you override hashCode method? Simply make some calculations that will always return same Integer number for same data.

@Override
public int hashCode() {
    int randomNumber = 13;
    int result = 1;
    result = randomNumber * result + (username == null ? 0 : username.hashCode());
    result = randomNumber * result + (firstname == null ? 0 : firstname.hashCode());
    result = randomNumber * result + (lastname == null ? 0 : lastname.hashCode());
    return result;
}