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, if
x.equals(y)
returntrue
, theny.equals(x)
Should also returntrue
- Transitivity: For multiple objects x,y,z, if
x.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 use
equals
Method that calls an object more than oncehashCode()
Method should return the same hash value. - If two objects pass
equals
Method comparison is equal, sorequirementsOf these two objectshashCode
The values returned by the methods should also be equal. - If two objects pass
equals
The method comparison is different, so alsoDoes not requireOf these two objectshashCode
Methods 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 defaulthashCode
It’s different. Of course it ishashMap
In 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()