Star: github.com/yehongzhi/l…

Writing in the front

In fact, I noticed a sentence in the Alibaba Java development specification that whenever you rewrite equals, you must rewrite hashCode.

I think a lot of people will ask why, the so-called know the why, knowledge is not only know the conclusion but also know the cause.

HashCode methods

The hashCode() method retrieves a hashCode and returns an int

For those of you who have studied data structures, the purpose of a hash code is to determine the index index of an object in a hash table. Hashsets and hashMaps, for example, use the hashCode method to determine index subscripts. If two objects return the same hashCode, it is called a “hash collision.”

The equals method

Equals () checks whether two objects are equal. The equals() method is defined in the Object class, and all classes have an Object parent. If you do not override the equals() method, you will call the equals() method of the Object class.

The equals method of the Object class uses the “==” number to compare two objects. In many cases, the == number compares the memory address of two objects rather than the actual value, so it is not very suitable for business purposes. So many times we need to override equals to compare the value of each member variable in an object.

The question

Why override hashCode () when you can compare two objects to be equal?

If hashCode is equal, then equals() will be used to compare the equals() method. In other words, a HashSet and a HashMap determine whether two elements are equal by determining the hashCode first. If the two objects have different Hashcodes, they must not be equal.

Let’s do an experiment. We have a User class that just overrides equals() and puts it into the Set.

public class User {

    private String id;

    private String name;

    private Integer age;
    
    public User(String id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null|| getClass() ! = o.getClass())return false;
        User user = (User) o;
        return Objects.equals(id, user.id) &&
            Objects.equals(name, user.name) &&
            Objects.equals(age, user.age);
    }
    
    Getters, setters, toString methods
}
Copy the code

We then loop through the creation of a User object with 10 member variables of the same value, and finally put it into the Set to duplicate.

public static void main(String[] args) {
    List<User> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        User user = new User("1"."Zhang".18);
        list.add(user);
    }
    Set<User> set = new HashSet<>(list);
    for (User user : set) {
        System.out.println(user);
    }
    List<User> users = list.stream().distinct().collect(Collectors.toList());
    System.out.println(users);
}
Copy the code

Logically we would expect to be de-weighted, leaving only a “triple” user, but in fact, because the hashCode method was not overridden, it was not de-weighted.

Then let’s rewrite some hashCode methods inside the User class and try again, nothing else.

public class User {
    // Nothing else
    
    // Override the hashCode method
    @Override
    public int hashCode(a) {
        returnObjects.hash(id, name, age); }}Copy the code

Run it again, and it works.

The reason for this is that HashSet determines whether hashCode is equal or not. If hashCode is not equal, the two objects are considered not equal and will not be compared using equals(). Let’s look at hash codes that override the hashCode method and those that don’t.

This is the case without overwriting the hashCode method; each user object has a different hashCode, so a HashSet will be considered unequal.

This is the case when the hashCode method is overridden, because the hashCode is computed using the values of all of the object’s member variables, so as long as the member variables of both objects are equal, the resulting hashCode is the same.

So some people look at this and say, well, if two objects return the same hash code, are they necessarily equal?

The answer is not always true, because hashsets and hashmaps also use equals() to determine hash values.

To sum up:

  • If the hash codes are not equal, the two objects must be different.
  • Hash codes are equal. Two objects are not necessarily the same.
  • If two objects are the same, the hash code and value must be equal.

conclusion

So going back to the beginning, whenever you override equals, you have to override hashCode, which is an important detail that can easily lead to business errors if you don’t pay attention to it.

In particular, if you use HashSet, distinct() to remove weights but it doesn’t work, you should look back and see if you overwrote equals() and hashCode().

So that’s all for this article. Thank you for reading.

The article continues to update, wechat search “Java technology enthusiasts”, the first time after paying attention to the technical article push, article classification is collected on github: github.com/yehongzhi, you can always find what you are interested in

Please give me a thumbs-up if you think it is useful. Your thumbs-up is the biggest motivation for my creation

I’m a programmer who tries to be remembered. See you next time!!

Ability is limited, if there is any mistake or improper place, please criticize and correct, study together!