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 Java
Article 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 Object
classes, and all classes in Java are Obejct
subclasses of classes, so all methods in Java will have default implementations of these two methods.
equals method
Object
The 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)
returnedtrue
, theny.equals(x)
should also be returnedtrue
- Transitivity: For multiple objects x, y, z, if
x.equals(y)
returntrue
,y.equals(z)
returntrue
, theny.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
Object
The hashCode()
method in is a native method that returns a int
hash 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
equals
if the parameters of the object being compared in the using method have not been modified.hashCode()
- If two objects
equals
are equal by method comparison, then the values returned by methods that require these two objectshashCode
should also be equal. - If two objects
equals
are 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 HashMap
the 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.
HashMap
It 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 hashCode
method. Remember that we mentioned the hashCode
method above that it is possible that hashCode
the 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 equals
method 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
hashCode
method. There are some other steps in the middle. Here, it can be simply consideredhashCode
that the position is determined.
When to override these two methods?
If you don't define the custom class as HashMap
the key value, then we override the equals
method without overriding the hashCode
method, the compiler will not report any error, and no exception will be thrown at runtime.
If you want to define a custom class as HashMap
the key value, then if you override the equals
method, you must also override the hashCode
method.
Next we can look at what happens when we use a custom class as HashMap
the key, and the custom class does not override equals
and hashCode
method.
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 null
value. 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 ishashCode
different, of course, inhashMap
would not consider the two to be one object.
Next, we will rewrite these two methods. If we use IDEA
it, 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
Lombock
the provided annotations@EqualsAndHashCode
Code address of this article
Past articles
- Learn these linked list algorithm questions, and you will no longer be afraid of handwritten linked lists for interviews.
- Is it that hard for Spring transactions to propagate properties? Enough to read this
- Back-end framework development needs to pay attention to
- The optimization process of compressing 20M files from 30 seconds to 1 second