This is a very classic question in Java and is often asked during interviews. In fact, many books or articles have mentioned that you have to overload hashCode() and equals() methods to realize the search for custom keys in HashMap. However, it seems that few articles talk about why you need to do this and what consequences will be caused by not doing this, so I will write this article to explain it.
First of all, what happens if we directly use the following Person class as key and store it in HashMap?
public class Person { private String id; public Person(String id) { this.id = id; }}import java.util.HashMap;public class Main { public static void main(String[] args) { HashMap<Person, String> map = new HashMap<Person, String>(); map.put(new Person("001"), "findingsea"); map.put(new Person("002"), "linyin"); map.put(new Person("003"), "henrylin"); map.put(new Person("003"), "findingsealy"); System.out.println(map.toString()); System.out.println(map.get(new Person("001"))); System.out.println(map.get(new Person("002"))); System.out.println(map.get(new Person("003"))); }}So what is the output result?
{Person@6e4d4d5e=henrylin, Person@275cea3=findingsea, Person@15128ee5=findingsealy, Person@4513098=linyin}nullnullnullWe can see that there are two problems here:
1. During the addition process, we added the key value pair of key=new Person("003") twice. In the expectation, there should only be one such key value pair in HashMap. Because the key (expected) is the same, it should not be added repeatedly. The value="findingsealy" added the second time should replace the original value="henrylin". But in the input, we found that the expected situation did not occur, but there are two key-value pairs of value="findingsealy" and value="henrylin" in HashMap, and their key values are still different, which is obviously wrong.
2. When getting the value value, we use three Person objects to search. These three objects are the same as the three key values we just stored (in expectation), but the search is three null values, which is obviously also wrong.
So, the correct method has actually been described in many places. The Person class is directly modified, overloaded equals and hashCode methods, and the modified Person class is as follows:
public class Person { private String id; public Person(String id) { this.id = id; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; if (id != null ? !id.equals(person.id) : person.id != null) return false; return true; } @Override public int hashCode() { return id != null ? id.hashCode() : 0; }}Then, when we re-execute the above inspection procedure, the results are as follows:
{Person@ba31=findingsea, Person@ba32=linyin, Person@ba33=findingsealy}findingsealinyinfindingsealyAs can be seen, all the highlights and errors pointed out have been corrected. So, why is this happening?
In HashMap, the order of comparison of search keys is:
1. Calculate the Hash Code of the object to see if it exists in the table.
2. Check whether the object in the corresponding Hash Code location is equal to the current object.
Obviously, the first step is to use the hashCode() method, and the second step is to use the equals() method. When no overloading is performed, these two methods of the Object class will be called by default in these two steps. In Object, the calculation method of Hash Code is calculated based on the object address. The object addresses of the two Person("003") are different, so their Hash Code is also different. Naturally, HashMap will not treat them as the same key. At the same time, in the default equals() of Object, it is also compared based on the object's address. Naturally, one Person("003") and another Person("003") are not equal.
After understanding this, it is easy to figure out why you need to overload both hashCode() and equals methods.
• Overloading hashCode() is to get the same Hash Code for the same key, so that the HashMap can be positioned on the key we specified.
• Overloading equals() is to show HashMap that the current object and the object saved on the key are equal, so that we can truly obtain the key-value pair corresponding to the key.
There is another detail. In the Person class, the emphasis on hashCode() method is:
@Overridepublic int hashCode() { return id != null ? id.hashCode() : 0;}The point that may be puzzled here is: Why can the Hash Code of a variable of type String be used as the Hash Code value of the Person class? Are the Hash Codes of new Person(new String("003")) and new Person(new String("003")) equal?
Let's take a look at the output of the following code:
System.out.println("findingsea".hashCode());System.out.println("findingsea".hashCode());System.out.println(new String("findingsea").hashCode());System.out.println(new String("findingsea").hashCode());728795174728795174728795174728795174You can see that the outputs of the four statements are all equal. It is very intuitive and reasonable to guess that the String type also overloads hashCode() to return the Hash Code value according to the content of the string, so strings with the same content have the same Hash Code.
At the same time, this also illustrates a question: Why do we need to use equals() for comparison when we know that hashCode() is equal? It is because it avoids the situation in the above example, because according to the overload implementation of the hashCode() method of the Person class, the Person class will directly use the Hash Code value of the String type member id as its Hash Code value. However, it is obvious that a Person("003") and a String("003") are not equal, so when hashCode() is equal, equals() is also needed to compare.
The following examples can be used as evidence of the above description:
System.out.println(new Person("003").hashCode()); // 47667System.out.println(new String("003").hashCode()); // 47667System.out.println(new Person("003").equals(new String("003"))); // falseThe above article Java uses customized classes as a key value example of HashMap. This is all the content I share with you. I hope it can give you a reference and I hope you can support Wulin.com more.