JavaRush /Java Blog /Random EN /Working with hashCode() and equals() methods in Java
Lenchik854
Level 0
Chernihiv

Working with hashCode() and equals() methods in Java

Published in the Random EN group
In this post I will outline my understanding of the methods hashCode()and equals(). I want to talk about their default implementation, as well as how to correctly override them. I'll also write about implementing these methods using the Apache Common package's helper classes. Working with hashCode() and equals() methods in Java - 1Contents of this post:
  1. Using hashCode()and equals().
  2. Override default behavior.
  3. Overriding hashCode()and equals()using Apache Commons Lang.
  4. Something that is important to remember.
  5. Special Attention When Using ORM.
hashCode()The and methods equals()were defined in the class Object, which is the parent class for java objects. Therefore, all java objects inherit the default implementation from these methods.

Using hashCode() and equals()

The method hashCode()is used to obtain a unique integer number for a given object. When an object needs to be stored as a data structure in a hash table (also called a bucket), this number is used to determine its location in that table. By default, the method hashCode()for an object returns the number of the memory location where the object is stored. The method equals(), as its name suggests, is used to simply check the equality of two objects. The default implementation of this method simply checks the references of two objects to see if they are equivalent.

Overriding default behavior

Everything works fine as long as you don't override any of these methods in your classes. But sometimes applications need to change the default behavior of some objects. Let's take an example where you have a Employee. Let's write the minimum possible structure of such a class.
public class Employee
{
    private Integer id;
    private String firstname;
    private String lastName;
    private String department;

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getFirstname() {
        return firstname;
    }
    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public String getDepartment() {
        return department;
    }
    public void setDepartment(String department) {
        this.department = department;
    }
}
The class described above Employeehas some basic attributes and accessor methods. Now let's look at a simple situation where we need to compare two objects of the class Employee.
public class EqualsTest {
    public static void main(String[] args) {
        Employee e1 = new Employee();
        Employee e2 = new Employee();

        e1.setId(100);
        e2.setId(100);
        //Печатает false в консоли
        System.out.println(e1.equals(e2));
    }
}
It doesn’t take a clairvoyant to guess that the above method will return “false”. But is this actually correct, given that these two objects are the same? In real time application, the method must return true. To achieve the correct behavior, we need to override the method equals(), as done below:
public boolean equals(Object o) {
        if(o == null)
        {
            return false;
        }
        if (o == this)
        {
           return true;
        }
        if (getClass() != o.getClass())
        {
            return false;
        }
        Employee e = (Employee) o;
        return (this.getId() == e.getId());
}
Add this method to your class Employeeand the equivalence check will return “true”. However, have we done everything? Not yet. Let's test our modified class in one more way.
import java.util.HashSet;
import java.util.Set;

public class EqualsTest
{
    public static void main(String[] args)
    {
        Employee e1 = new Employee();
        Employee e2 = new Employee();

        e1.setId(100);
        e2.setId(100);

        //Печатает 'true'
        System.out.println(e1.equals(e2));

        Set employees = new HashSet();
        employees.add(e1);
        employees.add(e2);
        //Печатает два an object
        System.out.println(employees);
    }
}
The command System.out.println(employee)prints two objects. If both objects were equivalent, and Setonly unique objects were contained in, then HashSetthere should be only one instance inside, i.e. both objects refer to the same instances of the class Employee. What have we missed? We missed the second important method hashCode(). As the java documentation says, if you override the method equals(), then you are required to override the method hashCode(). So let's add another method to our class Employee.
@Override
 public int hashCode()
 {
    final int PRIME = 31;
    int result = 1;
    result = PRIME * result + getId();
    return result;
 }
We added this method once to our class, and only one object will be printed, and thus, checking the equivalence of e1 and e2 showed true.

Overriding hashCode()and equals()using Apache Commons Lang

Apache Commons provides two great helper classes for calling methods hashCode()and equals(). Below we see the usage:
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
public class Employee
{
 private Integer id;
 private String firstname;
 private String lastName;
 private String department;
public Integer getId() {
    return id;
 }
 public void setId(Integer id) {
    this.id = id;
 }
 public String getFirstname() {
    return firstname;
 }
 public void setFirstname(String firstname) {
    this.firstname = firstname;
 }
 public String getLastName() {
    return lastName;
 }
 public void setLastName(String lastName) {
    this.lastName = lastName;
 }
 public String getDepartment() {
    return department;
 }
 public void setDepartment(String department) {
    this.department = department;
 }
@Override
 public int hashCode()
 {
    final int PRIME = 31;
    return new HashCodeBuilder(getId()%2==0?getId()+1:getId(), PRIME).
           toHashCode();
 }
@Override
 public boolean equals(Object o) {
    if (o == null)
       return false;
    if (o == this)
       return true;
    if (o.getClass() != getClass())
       return false;
    Employee e = (Employee) o;
       return new EqualsBuilder().
              append(getId(), e.getId()).
              isEquals();
    }
 }
On the other hand, if you use one of the code editors, they should also be able to call up some nice structures for you. For example, if in the Eclipse IDE you right-click on class >> source > Generating hashCode() and equals() ... it will generate a very nice implementation for you. Working with hashCode() and equals() methods in Java - 2Something that is important to remember.
  1. Always use the same object attributes to call both and hashCode()and equals(). Just in our case, we used employee id.
  2. The method equals()must be persistent (if the object has not changed, the method must return the same value).
  3. Whenever a.equals(b), then a.hashCode()must be the same as b.hashCode().
  4. If you override one method, you must override the second.

Special Attention When Using ORM

If you are dealing with ORM (ru.wikipedia.org/wiki/ORM), then always use getters and never use field references hashCode(). equals()This is because in an ORM, from time to time fields are loaded using lazy load and are not accessible until their getters are called. For example, in our class Employee, we use e1.id == e2.id. It's entirely possible that the id fields are loaded using lazy loading. One of the fields may be 0 or null and we will get incorrect behavior. But, if , is used e1.getId() == e2.getId(), we can be sure even if the fields were loaded using lazy loading; calling the getter will populate the field first. That's all I know about the hashCode()and methods equals(). Hope this helps someone somewhere. Good luck with your studies!! ps This is my first attempt at translation. I tried to convey everything as close as possible to what the author wanted to say. If you have any comments, please write in the comments. Don't judge strictly :-))) Original article
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION