Memory leak! Do you really understand the reason for overriding the equals() and hashcode() methods?

Basic concepts

  • To compare whether two objects are equal, you need to call the equals() method of the object:

    • Judge whether the object addresses pointed to by the object reference are equal
  • When the object addresses are equal, the data related to the object is also equal, including:

    • object handle
    • Object header
    • Object instance data
    • Object type data
  • You can determine whether objects are equal by comparing the addresses of objects

    Object source code

  • The Object uses the equals() method and hashCode() method in the Object without rewriting

    • equals(): determines whether the references of two objects point to the same object
    • hashCode(): generates an integer value based on the object address
  • The hashCode() method modifier of Object is native: indicating that the method is implemented by the operating system Java calls the underlying code of the operating system to obtain the Hash value

    public native int hashCode();

    Override equals

  • Scenarios for overriding the equals() method:

    • Suppose there are many students now
    • By default, to judge whether multiple student objects are equal, you need to judge according to the address:

      • If the object addresses are equal, the data of the object instance must be the same
    • Requirements for judging Equality:

      • When the students' names, ages and genders are equal, the objects are considered equal,
      • It is not necessary that the address of the object be exactly the same
  • Rewrite the equals() method as needed:

    public class Student {
      /** full name */
      private String name;
      /** Gender */
      private String sex;
      /** Age */
      private String age;
      /** weight */
      private float weight;
      /** address */
      private String addr;
    
      /*
       * Override the equals() method
       */
      @Override
      public boolean equals(Object obj) {
          // instanceof has handled the case of obj == null
            if (! (Object instanceof Student)) {
                
                return false;
            }
            Student stuObj = (Student) obj;
            // Address equality
            if (this == stuObj) {
                return true;
            }
            // If the name, age and gender of the object are equal Then the two objects are equal
            if (stuObj.name.equals(this.name) && stuObj.sex.equals(this.sex) && stuObj.age.equals(this.age)) {
                return true;
            } else {
                return false;
            }
       }
    
       public String getName() {
            return name;
       }
       public void setName(String name) {
            this.name = name;
       }
       public String getSex() {
            return sex;
       }
       public void setSex(String sex) {
            this.sex = sex;
       }
        public String getAge() {
            return age;
       }
       public void setAge(String age) {
            this.age = age;
       }
       public String getWeight() {
            return weight;
       }
       public void setName(String weight) {
            this.weight = weight;
       }
       public String getAddr() {
            return addr;
       }
       public void setAddr(String addr) {
            this.addr = addr;
       }
    }
  • Example:

    public static void main(String[] args) {
      Student s1 = new Student();
      s1.setAddr("earth");
      s1.setAge("20");
      s1.setName("Tom");
      s1.setSex("Male");
      s1.setWeight(60f);
    
      Student s2 = new Student();
      s2.setAddr("Mars");
      s2.setAge("20");
      s2.setName("Tom");
      s2.setSex("Male");
      s2.setWeight(70f);
    
      if (s1.equals(s2)) {
          System.out.println("s1 == s2");
      } else {
          System.out.println("s1 != s2");
      }
    }
  • After overriding the equals() method, [s1==s2] will be output here
  • If the equals() method is not overridden, it must output [s1!=s2]

    Override hashCode

  • According to the method of rewriting equals, s1 and s2 above are considered equal
  • hashCode() method in Object:

    • On the premise that the equals() method is not modified, the returned value of calling the hashCode() method of the same object multiple times must be the same positive number
    • If two objects are equal () to each other, the hashcode values of the two objects must be equal
    • Generating different hashcode s for different objects can improve the performance of Hash tables
  • Override hashCode() method:

    public class Student {
    /*Name/
    private String name;
    /*Gender/
    private String sex;
    /*Age/
    private String age;
    /*Weight/
    private float weight;
    /*Address/
    private String addr;

    /*

    • Override hashCode() method
      */

    @Override
    public int hashCode() {

       int result = name.hashCode();
       result = 17 * result + sex.hashCode();
       result = 17 * result + age.hashCode();
       return result;

    }

    /*

    * rewrite equals()method
    */

    @Override
    public boolean equals(Object obj) {

        // instanceof has handled the case of obj == null
        if (! (Object instanceof Student)) {
            
            return false;
        }
        Student stuObj = (Student) obj;
        // Address equality
        if (this == stuObj) {
            return true;
        }
        // If the name, age and gender of the object are equal Then the two objects are equal
        if (stuObj.name.equals(this.name) && stuObj.sex.equals(this.sex) && stuObj.age.equals(this.age)) {
            return true;
        } else {
            return false;
        }

    }

    public String getName() {

        return name;

    }
    public void setName(String name) {

        this.name = name;

    }
    public String getSex() {

        return sex;

    }
    public void setSex(String sex) {

        this.sex = sex;

    }
    public String getAge() {

        return age;

    }
    public void setAge(String age) {

        this.age = age;

    }
    public String getWeight() {

        return weight;

    }
    public void setName(String weight) {

        this.weight = weight;

    }
    public String getAddr() {

        return addr;

    }
    public void setAddr(String addr) {

        this.addr = addr;

    }
    }

  • When two objects are equal, put them into Map and Set respectively:

    public static void main(String[] args) {
      Student s1 = new Student();
      s1.setAddr("earth");
      s1.setAge("20");
      s1.setName("Tom");
      s1.setSex("Male");
      s1.setWeight(60f);
    
      Student s2 = new Student();
      s2.setAddr("Mars");
      s2.setAge("20");
      s2.setName("Tom");
      s2.setSex("Male");
      s2.setWeight(70f);
    
      if (s1.equals(s2)) {
          System.out.println("s1 == s2");
      } else {
          System.out.println("s1 != s2");
      }
      
      Set set = new HashSet();
      set.add(s1);
      set.add(s2);
      System.out.println(Set);
    }
  • If the hashCode() method of the Object is not overridden, the following occurs:

    [com.oxford.Student@7852e922, com.oxford.Student@4e25154f]
  • This is not expected because the Set container has the feature of de duplication Equal elements are not repeated This involves the underlying implementation of Set
  • HashSet underlying implementation:

    • The bottom layer of HashSet is implemented through HashMap
    • Whether the elements in the Set container are equal is determined by comparing the hashcode of the object
  • hashCode():

    • First, sort out the attributes that judge the equality of objects
    • Then go to a positive integer as small as possible to prevent the final result from exceeding the retrieval range of integer int
    • Then calculate [hashCode of positive integer * attribute + hashCode of some other attribute]
    • Repeat step
    /*
     * Override hashCode() method
     */
    @Override
    public int hashCode() {
      int result = name.hashCode();
      result = 17 * result + sex.hashCode();
      result = 17 * result + age.hashCode();
      return result;
# Principle analysis
- Because the parent class is not overridden**Object**of**hashCode()** method,therefore**Object**of**hashCode()** Method generates a response based on the addresses of the two objects**hashcode**
- Because the two objects are different instances created by entity classes,So the address must be different,that**hashcode**The value is also different
- **Set Is the distinguishing object the only criterion:**
  - Of two objects**hashcode**Are the values the same
  - Then determine whether the two objects are**equals** 
- **Map Is the distinguishing object the only criterion:**
  - First according to**Key**Value**hashcode**Assign to get the index of the saved array
  - Then according to**eaquals**Distinguish whether it is a unique value 
# HashMap
### HashMap composition structure
- **HashMap:** By**array**and**Linked list**Composed
### Storage of HashMap
- **HashMap Storage of:**
  - An object is stored in**HashMap**The position in is determined by**key**of**hashcode**Value determined 
  - **HashMap lookup key:**
    - lookup**key**Time **,hashMap**According to**key**Value**hashcode**After the remainder algorithm, locate the position of the array
    - Then according to**key**of**equals**Method matches the same**key**Value to get the corresponding object 
- **Stored value rule:**
  - take**Key**of**hashcode**And**HashMap**Capacity of,conduct**Surplus**Calculate the**Key**The subscript stored in the location of the array
- **HashMap lookup key:**
  - obtain**key**Position in array
  - Match to get the corresponding**key**Value object
  - Then, according to the above multiple objects**key.equals()** To match and obtain the corresponding key Data object for
- **HashMap Medium hashCode:** 
  - without**hashcode**That means**HashMap**There are no rules to follow when storing

Keywords: Java Spring Memory Leak

Added by eletrium on Wed, 15 Dec 2021 16:14:34 +0200