Why override hashCode() when you override equals()

The author’s writing skill is still shallow, if there is something wrong, please point out generously, will be grateful

In Effective Java, article 9 states that hashCode() should always be overridden when overriding equals(). Why is that? Let’s take a look at these two methods.

The Equals () and hashCode() methods in Java are methods in the Object class, and all classes in Java are subclasses of the Obejct class, so all methods in Java have default implementations of these two methods.

The equals method

The equals() method in the Object class is defined as follows

1public boolean equals(Object obj) {

2    return (this == obj);

3}

Copy the code

We found the key == in equals(), so what does == mean in Java? We all know that Java is divided into primitive data types and reference data types. So == works differently in these two types.

  • Basic data types: The comparison is= =Are these values equal to each other
  • Reference data types: The comparison is= =Whether the two memory addresses are the same

Basic data types include: byte, short, char, int, long, float, double, Boolean

According to the Equals () method described in the Java documentation, all who want to implement their equals() method must follow the following rules

  • Reflexivity: For any object X,x.equals(x)Should be returnedtrue
  • Symmetry: For any two objects X and y, ifx.equals(y)returntrue, theny.equals(x)Should also returntrue
  • Transitivity: For multiple objects x,y,z, ifx.equals(y)returntrue.y.equals(z)returntrue, theny.equals(z)Should also returntrue
  • Consistency: For two non-empty objects x,y, multiple calls should return the same result without modifying the object
  • For any non-empty object x,x.equals(null)Should returnfalse

HashCode methods

The hashCode() method in Object is a native method that returns a hash of type int.

1public native int hashCode(a);

Copy the code

There are also some conventions in the hashCode() method

  • If the object is in useequalsMethod that calls an object more than oncehashCode()Method should return the same hash value.
  • If two objects passequalsMethod comparison is equal, sorequirementsOf these two objectshashCodeThe values returned by the methods should also be equal.
  • If two objects passequalsThe method comparison is different, so alsoDoes not requireOf these two objectshashCodeMethods return different values. But we should know that producing different hash values for different objects can improve performance for hash tables (hashmaps, etc.).

Where are the equals and hashCode methods used

Which class in Java do these two methods appear most often? Those of you who have read the HashMap source code should know that these two methods appear frequently in HashMap. There are many articles on the web that introduce the HashMap class. Here is a brief introduction to HashMap.

When the list in a node exceeds 8, it will become a red-black tree to solve the problem of slow query speed when the list is too long.

A HashMap is an efficient data storage structure composed of arrays and linked lists. So how do you figure out where a data is stored in an array? It’s just using the hashCode method to figure out where it’s stored. Remember we talked about the hashCode method above and we said that it’s possible for two different objects to return the same value, and then there’s a conflict, and if there’s a conflict, we call equals. If they’re different, Add them to the end of the list and replace them if they are the same.

Of course, it’s not as simple as a hashCode method above. There are other steps in between, and we can simply say that hashCode determines the position.

When do you override these two methods?

If you do not define a custom class as a HashMap key, then we override equals instead of hashCode, and the compiler does not raise any errors and does not throw any exceptions at runtime.

If you want to define a custom class as the key value of a HashMap, then overriding equals must also override the hashCode method.

Next we can see what happens if we use a custom class as the key of a HashMap and the custom class does not override equals and hashCode methods.

Custom classes

1@Builder

2@NoArgsConstructor

3@AllArgsConstructor

4class CustomizedKey{

5    private Integer id;

6    private String name;

7}

Copy the code

Let’s look at using a custom class as key

 1    public static void main(String[] args{

2

3        Map<CustomizedKey, Integer> data = getData();

4

5        CustomizedKey key = CustomizedKey.builder().id(1).name("key").build();

6

7        Integer integer = data.get(key);

8

9        System.out.printf(String.valueOf(integer));

10    }

11

12    private static Map<CustomizedKey,Integer> getData(){

13        Map<CustomizedKey,Integer> customizedKeyIntegerMap = new HashMap<>();

14        CustomizedKey key = CustomizedKey.builder().id(1).name("key").build();

15        customizedKeyIntegerMap.put(key,10);

16        return customizedKeyIntegerMap;

17    }

Copy the code

We can see that the program finally prints a null value. The reason is as we said above.

  • hashCode: is used to calculate the location of the object in the array, because the two objects are new, so even though the value inside is the same, the address of the object is different, so use the defaulthashCodeIt’s different. Of course it ishashMapIn would not consider two objects to be one.

So let’s rewrite these two methods. If we use IDEA, we can just use the shortcut keys.

Let’s look at the two methods we implement

 1@Builder

2@NoArgsConstructor

3@AllArgsConstructor

4class CustomizedKey{

5    private Integer id;

6    private String name;

7

8    @Override

9    public boolean equals(Object o) {

10        if (this == o) return true;

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

12        CustomizedKey that = (CustomizedKey) o;

13        return Objects.equals(id, that.id) &&

14                Objects.equals(name, that.name);

15    }

16

17    @Override

18    public int hashCode() {

19        return Objects.hash(id, name);

20    }

21}

Copy the code

Then we run the program again and find that the output print has changed to 10.

We can also simplify the code using the @equalSandhashCode annotation provided by Lombok

This article code address

The articles

  • Learn these list algorithm questions, interviews are no longer afraid of handwritten list
  • Is it so hard for Spring transactions to propagate properties? This one is enough
  • Some considerations for backend framework development
  • Compress 20M files from 30 seconds to 1 second optimization process

Refer to the article

  • [Java Object source]()
  • Java equals() and hashCode()