Location>code7788 >text

Sorting out equals and hashCode relationships

Popularity:310 ℃/2024-08-26 13:48:30

catalogs
  • equals usage
  • hashCode Usage
  • summarize
  • Why do you need two comparison methods in a class
  • Why is it necessary to override the hashCode method when overriding the equals method?
  • Reference


This is not a generic programming problem, but rather one that is proprietary to the Java domain.

Be prepared for the fact that this is a complex class question, and to answer it, you need to sort out the relationship between the two functions and the other classes, and that they are somewhat intertwined.

equals usage

The Object class also contains the equals() method:

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

Description:

  • == For comparisonvariantstored in the memory corresponding to thenumerical valueWhether or not they are the same, to compareTwo basic types of data (note the basic types)maybeTwo reference variablesWhether they are equal or not, only the == operator can be used.

hashCode Usage

The hashCode() method is also included in the Object class:

public native int hashCode();

Please answer, why does the Object class need a hashCode() method?

In Java, the main purpose of the hashCode() method is to work with hash tables.

Hash table (Hash Table), also known as the hash table, is a data structure that can be accessed directly through the key code value (key-value), its biggest feature is that it can be quickly implemented to find, insert and delete. One of the algorithms used is called hash, which is any length of the input, transformed into a fixed length of the output, the output is the hash value. Like MD5, SHA1 are used in the hash algorithm.

Like Java's HashSet, Hashtable, HashMap are based on the specific implementation of the hash table. HashMap is the most typical representative.

Think about it, people.If there is no hash table, but there is a need for such a data structure, which holds data that is not allowed to be duplicated, how is it implemented?

  • √ How about using the equals() method to do a case-by-case comparison? This option is certainly possible.
    However, if the amount of data is particularly large, the efficiency of using the equals() method to compare one by one must be very, very low, to summarize: it can be solved, but it is not very efficient.
  • √√ The best solution is a hash table. To summarize: it's not just a solution, it's also inefficient.

Case Notes:
Take a HashMap for example, when we want to add an object to it, we first call the hashCode() method of the object, get the corresponding hash value, and then put the hash value and the object into the HashMap together. When we want to add a new object:

  1. Gets the hash value of the object;
  2. Compare it with a previously existing hash, and if it's not equal, store it directly;
  3. If there is an equal, then call the equals() method to compare between the objects, and if they are equal, don't store them;
  4. If it doesn't wait, there is a hash conflict, and a chained table is added to hold the new object;
  5. If the length of the linked table is greater than 8, it is converted to a red-black tree.

With just this set, the frequency of calls to the equals() method is greatly reduced. That is, hash tables are particularly efficient as long as the hashing algorithm is efficient enough to minimize the frequency of hash conflicts.

summarize

== is used to compare whether the values stored in the memory corresponding to the variables are the same. To compare two basic types of data (note that they are basic types) or two reference variables, you can only use the == operator.

equals comparesValue and address, which has the same effect as == if the equals method is not overridden;
In the String class, the equals method is overridden to compare the(be) worthAre they equal;

hashCode is used in the hash data structure of thehash value calculation

equals two objects are equal, that hashcode must be equal, hashcode is equal, not necessarily the same object (hash conflict phenomenon);
hashCode is generally used together with equals, when comparing two objects as "equal", the hashCode is the same as the equals.precondition.

Why do you need two comparison methods in a class

Because of the rewrite of equals() in the general comparison of the more comprehensive and more complex, so that the efficiency is relatively low, and the use of hashCode () for comparison, as long as the generation of a hash value for comparison can be, the efficiency is very high, then hashCode () since the efficiency of such a high why equals() it?

  • Because hashCode() is not completely reliable, and sometimes different objects will have the same hashcode (hash conflict), hashCode() can only be said to be reliable most of the time, but not absolutely reliable.

  • Two objects that equals() must have equal hashCode(), which means that comparing with equals() is absolutely reliable.

Why is it necessary to override the hashCode method when overriding the equals method?

You can start by looking at some of the advice given by Java this B, which is to specify beforehand...

public class Object {

    /**
     * Returns a hash code value for the object. This method is
     * supported for the benefit of hash tables such as those provided by
     * ``.
     *
     * The general contract of `hashCode` is:
     *
     * a) Whenever it is invoked on the same object more than once during
     *    an execution of a Java application, the `hashCode` method must
     *    consistently return the same integer, provided no information
     *    used in `equals` comparisons on the object is modified.
     *    This integer need not remain consistent from one execution of an
     *    application to another execution of the same application.
     *
     * b) If two objects are equal according to the `equals(Object)` method,
     *    then calling the `hashCode` method on each of the two objects must
     *    produce the same integer result.
     *
     * c) It is not required that if two objects are unequal according to the
     *    `equals(Object)` method, then calling the `hashCode` method on each of
     *    the two objects must produce distinct integer results.
     *    However, the programmer should be aware that producing distinct integer
     *    results for unequal objects may improve the performance of hash tables.
     */
    @IntrinsicCandidate
    public native int hashCode();

    /**
     * Indicates whether some other object is "equal to" this one.
     *
     * @apiNote
     * It is generally necessary to override the `hashCode` method whenever this
     * method is overridden, so as to maintain the general contract for the `hashCode`
     * method,  which states that equal objects must have equal hash codes.
     */
    public boolean equals(Object obj) {
        return (this == obj);
    }
}

The above describes the three general conventions listed in the comment of the hashCode method, and the comment of the equals method also has this sentence: "Whenever you rewrite the equals method, you need to rewrite the hashCode method so that you don't break the general convention of the hashCode method, i.e., if two objects are Equal (the equals method is called as i.e., if two objects are Equal (the call to the equals method is true), then the call to the hashCode method on each of the two objects needs to return the same hash value".

So overriding only the equals method without overriding the hashCode method may result in two objects calling the equals method true but with different hashCode values, which may result in abnormal behavior.

What is this scenario?
The hashCode() of two equal Person objects p1 and p2 are different because the hashCode() method is not overridden in the Person class, they use the default implementation of the hashCode() method inherited from the Object class.

In the Object class, the default implementation of the hashCode() method returns the value of the object's memory address as a hash code.

Summary:
It's just a convention. It's also for logical self-consistency.

Reference

Java hashCode method in-depth analysis
/basic-extra-meal/

Java: Why is it necessary to override the equals method along with the hashCode method?
/posts/