Why override equals() also override hashCode()

Why override equals() also override hashCode()

The author's writing skills are still shallow, if there is anything wrong, please point out generously, I will be grateful

In Effective JavaArticle 9, it is stipulated that when you override equals()a method, always override the hashCode()method. Why is this? Next, we will introduce these two methods.

equals()Methods and hashCode()methods in Java are methods in Objectclasses, and all classes in Java are Obejctsubclasses of classes, so all methods in Java will have default implementations of these two methods.

equals method

ObjectThe methods in the class are equals()defined as follows

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

We found that the equals()key is in the method ==, so ==what is the meaning in Java? We all know that there are basic data types and reference data types in Java. So ==the role of these two types is not the same.

  • Basic data type: compares ==whether the values ​​on both sides are equal
  • Reference data type: compare ==whether the memory addresses on both sides are equal

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

equals()And through the method description in the Java document , all methods that want to implement their own equals()must comply with the following rules

  • Reflexive: for any object x, x.equals(x)should returntrue
  • Symmetry: For any two objects x and y, if x.equals(y)returned true, then y.equals(x)should also be returnedtrue
  • Transitivity: For multiple objects x, y, z, if x.equals(y)return true, y.equals(z)return true, then y.equals(z)it should also returntrue
  • Consistency: For two non-null objects x, y, the results returned by multiple calls should be the same without modifying the object.
  • For any non-null object x, x.equals(null)should returnfalse

hashCode method

ObjectThe hashCode()method in is a native method that returns a inthash of the type.

public native int hashCode();

hashCode()There are also some conventions in the method

  • Multiple calls to an object's method should return the same hash value equalsif the parameters of the object being compared in the using method have not been modified.hashCode()
  • If two objects equalsare equal by method comparison, then the values ​​returned by methods that require these two objects hashCodeshould also be equal.
  • If two objects equalsare different through method comparison, then it is also nothashCode required that the values ​​returned by the methods of the two objects are the same. But we should know that generating different hash values ​​for different objects can improve performance for hash tables (HashMap, etc.).

Where will equals method and hashCode method be used

In which class in Java do these two methods often appear? If you have read HashMapthe source code, you should know that these two methods often appear in HashMap. There are many articles on the Internet HashMap, so here is a brief introduction HashMap.

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

HashMapIt is an efficient data storage structure composed of arrays and linked lists. So how do you determine where a piece of data is stored in an array? It is to calculate where to store it through the hashCodemethod. Remember that we mentioned the hashCodemethod above that it is possible that hashCodethe values ​​returned by the methods of two different objects are the same, then a conflict will occur at this time. If a conflict occurs, the equalsmethod will be called for comparison. , if different, add it to the tail of the linked list, if it is the same, replace the original data.

Of course, the calculation of the position is not calculated by the above simple hashCodemethod. There are some other steps in the middle. Here, it can be simply considered hashCodethat the position is determined.

When to override these two methods?

If you don't define the custom class as HashMapthe key value, then we override the equalsmethod without overriding the hashCodemethod, the compiler will not report any error, and no exception will be thrown at runtime.

If you want to define a custom class as HashMapthe key value, then if you override the equals method, you must also override the hashCodemethod.

Next we can look at what happens when we use a custom class as HashMapthe key, and the custom class does not override equalsand hashCodemethod.

custom class

@Builder
@NoArgsConstructor
@AllArgsConstructor
class CustomizedKey{
    private Integer id;
    private String name;
}

Next we look at using a custom class as a key

    public static void main(String[] args) {
        
        Map<CustomizedKey, Integer> data = getData();
        
        CustomizedKey key = CustomizedKey.builder().id(1).name("key").build();
        
        Integer integer = data.get(key);
        
        System.out.printf(String.valueOf(integer));
    }

    private static Map<CustomizedKey,Integer> getData(){
        Map<CustomizedKey,Integer> customizedKeyIntegerMap = new HashMap<>();
        CustomizedKey key = CustomizedKey.builder().id(1).name("key").build();
        customizedKeyIntegerMap.put(key,10);
        return customizedKeyIntegerMap;
    }

We can see that the last thing the program prints is a nullvalue. The reason is the same as we said above.

  • hashCode: used to calculate where the object is placed in the array, because both are new objects, so even if the value inside is the same, the address of the object is different, so the default is hashCodedifferent, of course, in hashMapwould not consider the two to be one object.

Next, we will rewrite these two methods. If we use IDEAit, we can use the shortcut keys directly.

Next we look at the two methods we implemented

@Builder
@NoArgsConstructor
@AllArgsConstructor
class CustomizedKey{
    private Integer id;
    private String name;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CustomizedKey that = (CustomizedKey) o;
        return Objects.equals(id, that.id) &&
                Objects.equals(name, that.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }
}

Then we run the above program again and find that the output print has become 10.

We can also simplify the code using Lombockthe provided annotations@EqualsAndHashCode

Code address of this article

Past articles

Reference article

{{o.name}}
{{m.name}}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324123620&siteId=291194637