Last Updated:

Equals method in Java

In their work, programmers often have to check the equality of objects. Let's take a look at how the Java comparison works.

Comparison with == and equals in Java

Sample code:

String s1 = new String(«vscode.com»);
String s2 = new String(«vscode.com»);

System.out.println(s1 == s2); what will be the result of the comparison here?
System.out.println(s1.equals(s2)); and here?

What is the difference between these records? What is the difference between the comparison operator == and the equals method?
It's actually easy. When comparing, the equals method checks and matches the values of objects and on the basis of this comes to the conclusion of the wound whether they are true or not (true or false).

The == operator compares the value of variables (in the case of primitive data types) and returns the result. However, in the case of reference data types (arrays, objects, and so on), it compares references to objects in pc memory, and based on the analysis, it gives the result true or false. That's all the difference between the equals method and the == operator in Java.

The equals method is a method of the Object class. However, each object is implicitly inherited from the Object class and is capable of calling the equals method. Consider the example we gave above. We can conclude about the result of the comparison operation in two cases:

  • System.out.println(s1 == s2); returned false. Links are compared, but they are different.
  • System.out.println(s1.equals(s2)); true is returned because the object values are equal (they are the same).

Importantly! Instead of a String class, any other reference data type can be declared (your custom class, ArrayList<>, Object, and so on).

Overriding the equals method in Java

When do I need to predefine the equals method? This should be done when the concept of logical equivalence for your class is defined. In this case, the equivalence does not coincide with the identity of objects. For example, this concept can be applied to the String and Integer classes.

Overriding the equals method is required not only to meet the expectations of programmers. With it, you can use class instances as keys in a specific schema or elements in a set with necessary and predictable behavior. What does that mean?

Here's an example of the code:

public class Address {
private Integer number;
private String street;

public Address(Integer number, String street) {
this.number = number;
this.street = street;

}

public Integer getNumber() {
return number;

}

public String getStreet() {
return street;

}

public static void main(String[] args) {
List<Address> addressList = new ArrayList<>();
addressList.add(new Address(1, "Test street"));
addressList.add(new Address(1, "Test street"));
while (addressList.remove(new Address(1, "Test street")));
System.out.println(addressList.size());

}
}

In the example, we create a list of Address objects where we add an object of the Address class with an identical constructor. Add this object twice to the List, and use a loop to get rid of it. Next, display the length of the list in the console.

As a result, the number 2 will be displayed in the console after running the program. The question arises: "Why did the number of entries in the list remain unchanged? After all, our task is to remove them." In this example, objects with the same number and street fields, but they are not deleted.

When objects are removed from the list, the equals method is implicitly called, and if the object passed for deletion is in the list, it is deleted. Using the equals method in the Object class only checks for link equality. Examplators have different references, since they are different objects, each of them was developed using the new operator. How to solve this problem?

The answer is obvious – you need to predefine the equals method in the Address class:

@Override
public boolean equals(Object o) {
if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

Address address = (Address) o;

if (number != null ? !number.equals(address.number) : address.number != null)
return false;

if (street != null ? !street.equals(address.street) : address.street != null)
return false;

return true;
}

After running the program, you will see that the number of objects in the list is now zero.

Rules for overriding the equals method in Java

There are five rules for overriding the equals method in Java:

  1. Symmetry: For all zero objects x and y, the expression x.equals(y) should return true only when equals(x) returns true.
  2. Reflexivity: For each non-zero object x, the expression x.equals(x) must return a Boolean value of true.
  3. Transitivity: for 3 non-zero objects x, y and z, if x.equals(y) returns Boolean true and u.equals(z) returns true, then the expression x.equals(z) should return true.
  4. Consistency: If you call x.equals multiple times for all non-zero objects, you should always return false or true, except if no information in the objects has changed.
  5. For all non-zero x, the expression x.equals(null) must return a Boolean value of false.

For those who are not strong in mathematics, it all looks rather strange. But try to figure it out by carefully re-reading everything a few times. In fact, there is nothing complicated here. These rules cannot be broken, otherwise the application will run unstable and often fail. At the same time, it will not be easy to find out the source of the error of this class.