Java hashCode () and equals () of a number of related issues

table of Contents

​​​​​​​​​​​​​​

Effect Part 1 equals () of

What is the difference Part 2 equals () and == is?

Part 3 Effect hashCode () of

Part 4 Relationship hashCode () and equals () of


Effect Part 1 equals () of

action equals () is  used to determine whether two objects are equal .

equals () defined in the JDK Object.java. Determining whether the two objects are equal by the address (i.e., whether the same object) to distinguish whether they are equal. Source as follows:

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

Since Object.java defined equals () method, which means that all Java classes implement equals () method, all classes can go to compare whether two objects are equal by the equals (). However, as we have said, using the default " the equals () " method, equivalent to " == " approach. Therefore, we will usually override the equals () method: If the contents of the two objects are equal, then the equals method returns true (); otherwise, it returns fasle.  

Here "The Overwrite equals () method of class ", which will be divided into two types.
(01) If a class does not cover the method equals (), when it is through equals () compares two objects, two objects are actually the comparison is not the same object. At this point, equivalent to the "==" to compare the two objects.
(02) we can cover class equals () method to let the equals () Compares two objects are equal by other means. The usual practice is: If the contents of an object are equal, equals () method returns true; otherwise, return fasle.


Hereinafter, Examples of the above two cases will be described.

1. "no coverage equals () method" in

Code below (EqualsTest1.java) :

import java.util.*;
import java.lang.Comparable;

/**
 * @desc equals()的测试程序
 *
 */
public class EqualsTest1{

    public static void main(String[] args) {
        // 新建2个相同内容的Person对象,
        // 再用equals比较它们是否相等
        Person p1 = new Person("eee", 100);
        Person p2 = new Person("eee", 100);
        System.out.printf("%s\n", p1.equals(p2));
    }

    /**
     * @desc Person类。
     */
    private static class Person {
        int age;
        String name;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String toString() {
            return name + " - " +age;
        }
    }
}

Operating results :

false

Analysis of the results :

       We p1.equals (p2) to "compare p1 and p2 are equivalent, so." In fact, Object.java of calls equals () method, which calls (p1 == p2). It is more "p1 and p2 is whether the same object."
       By definition the p1 and p2, although they are the same content; however, they are two different objects! Therefore, the result is false.

2. " coverage equals () method " case

We modify the above EqualsTest1.java : coverage equals () method .

Code below (EqualsTest2.java) :

import java.util.*;
import java.lang.Comparable;

/**
 * @desc equals()的测试程序
 *
 */
public class EqualsTest2{

    public static void main(String[] args) {
        // 新建2个相同内容的Person对象,
        // 再用equals比较它们是否相等
        Person p1 = new Person("eee", 100);
        Person p2 = new Person("eee", 100);
        System.out.printf("%s\n", p1.equals(p2));
    }

    /**
     * @desc Person类。
     */
    private static class Person {
        int age;
        String name;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String toString() {
            return name + " - " +age;
        }

        /** 
         * @desc 覆盖equals方法 
         */  
        @Override
        public boolean equals(Object obj){  
            if(obj == null){  
                return false;  
            }  
              
            //如果是同一个对象返回true,反之返回false  
            if(this == obj){  
                return true;  
            }  
              
            //判断是否类型相同  
            if(this.getClass() != obj.getClass()){  
                return false;  
            }  
              
            Person person = (Person)obj;  
            return name.equals(person.name) && age==person.age;  
        } 
    }
}

Operating results :

true

Analysis of the results :

We rewrite the Person of equals () function in the EqualsTest2.java: When two Person object name and age are equal, it returns true.
Therefore, the results returned true.

In talking about this, by the way java requirements for equals () is. The following points:

1. 对称性:如果x.equals(y)返回是"true",那么y.equals(x)也应该返回是"true"。
2. 反射性:x.equals(x)必须返回是"true"。
3. 类推性:如果x.equals(y)返回是"true",而且y.equals(z)返回是"true",那么z.equals(x)也应该返回是"true"。
4. 一致性:如果x.equals(y)返回是"true",只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是"true"。
5. 非空性,x.equals(null),永远返回是"false";x.equals(和x不同类型的对象)永远返回是"false"。

Then review the equals () role: to determine whether two objects are equal. When we rewrite equals (), and be sure it is not good to change the role!

 

What is the difference Part 2 equals () and == is?

==: its role is to determine if the address is not equal to the two objects. That is, it is determined again two objects are not the same object.

equals (): its role is determined whether the two objects are equal. It is generally used in two cases (mentioned in section 1 have been described in detail before):
                 1. does not cover type equals () method. Through equals () comparing two objects of the class, is equivalent to the "==" to compare the two objects.
                 Case 2, class overrides the equals () method. Generally, we cover the equals () method is equal to the contents of two objects; if their contents are equal, returns true (that is, the two objects are considered equal).

Here, by way of example the differences between them.

code show as below

import java.util.*;
import java.lang.Comparable;

/**
 * @desc equals()的测试程序
 *
 */
public class EqualsTest3{

    public static void main(String[] args) {
        // 新建2个相同内容的Person对象,
        // 再用equals比较它们是否相等
        Person p1 = new Person("eee", 100);
        Person p2 = new Person("eee", 100);
        System.out.printf("p1.equals(p2) : %s\n", p1.equals(p2));
        System.out.printf("p1==p2 : %s\n", p1==p2);
    }

    /**
     * @desc Person类。
     */
    private static class Person {
        int age;
        String name;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String toString() {
            return name + " - " +age;
        }

        /** 
         * @desc 覆盖equals方法 
         */  
        @Override
        public boolean equals(Object obj){  
            if(obj == null){  
                return false;  
            }  
              
            //如果是同一个对象返回true,反之返回false  
            if(this == obj){  
                return true;  
            }  
              
            //判断是否类型相同  
            if(this.getClass() != obj.getClass()){  
                return false;  
            }  
              
            Person person = (Person)obj;  
            return name.equals(person.name) && age==person.age;  
        } 
    }
}

Operating results :

p1.equals(p2) : true
p1==p2 : false

Analysis of the results :

In the EqualsTest3.java:
(01)  p1.equals (p2) 
        which is the content is determined p1 and p2 are equal. Because the cover Person equals () method, and this equals () is used to determine whether the content is equal to p1 and p2, p1 and content exactly equal to p2, and; thus, returns true.

(02)  p1 == p2
       which is to determine whether p1 and p2 are the same object. Because they are two respective new Person object; therefore, returns false.

 

Part 3 Effect hashCode () of

action hashCode () is acquired hash code , also called a hash code; it actually returns an int integer. The role of the hash code is to determine the location of the object in the hash index table.

hashCode () is defined in the JDK Object.java, this means that any Java class contains a hashCode () function.
        Although each Java class contains hashCode () function. But just when created and a "class hash table" (on "hash table" see below), the class hashCode () is only useful (role is to: determine the class of each object in the hash table position; in other cases (e.g., a single object class is created, creating an array or an object class, etc.), class hashCode () has no effect.
       the above hash table, means that: Java collection class is essentially the hash table such as HashMap, Hashtable, HashSet.

       In other words: hashCode () is only useful in the hash table, in other cases useless. Action hashCode () is acquired in the hash table is a hash code of the object, and to determine the position of the object in the hash table.

OK! At this point, we figure it out: the role of hashCode () is to obtain a hash code. However, the hash code is used to doing it? Why hash code hash table need it? To solve these problems, we need to understand hash table! Details about the hash table, non-road a few words to understand; we can learn through the following articles:

[Reserved] hash table (Hash Table) from the theoretical to the practical (on)

[Reserved] hash table (Hash Table) from the theoretical to the practical (in)

[Reserved] hash table (Hash Table) from the theoretical to the practical (lower) 

In order to understand the following discussion, here a brief look at the role of the hash code.

我们都知道,散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!
散列表的本质是通过数组实现的。当我们要获取散列表中的某个“值”时,实际上是要获取数组中的某个位置的元素。
而数组的位置,就是通过“键”来获取的;更进一步说,数组的位置,是通过“键”对应的散列码计算得到的。

Below, we HashSet an example to further illustrate hashCode () role.

        Assumptions, HashSet already has 1000 elements. When inserting the first 1001 elements need to how to deal with? Because HashSet is a collection of Set, which allows duplicate elements.
        "1001 will be the first element-by-element 1000 and earlier to compare"? Obviously, this is equal to the low efficiency. Hash good solution to this problem, which calculates the position of the element in the hash table based on the hash code element, then the element can be inserted into the location. For the same elements, nature is only saved one.
        It can be seen, when the two elements are equal, their hash code must be equal; but the reverse is not necessarily correct. In the hash table,
                           1, if the two objects are equal, then their hashCode () value must be the same;
                           2, if two objects hashCode () are equal, they are not necessarily equal.
                           Note: This is the case in the hash table. Necessarily the case in a non-hash table!

On "The role of hashCode () is" to talk about so much.

 

Part 4 Relationship hashCode () and equals () of

Then the following, we discuss another topic. Many online article will hashCode () and equals associates, some say not thorough, there are suspected of misleading readers. Here, I sort out a bit "relationship hashCode () and equals () of."

We " category of use " to the "relationship hashCode () and equals ()" divide two cases to illustrate.

1. The first does not create a "class corresponding hash table"

         Here the word "will not create a class corresponding hash table" is to say: we are not in a data structure HashSet, Hashtable, HashMap, etc. These are essentially in the hash table, use the class. For example, do not create a HashSet collection class.

        In this case, "hashCode () and equals ()" is not half dime that class!
        In this case, equals () is used to compare two objects of that class are equal. The hashCode () then do not have any effect, so it does not matter hashCode ().

Below, we see an example of the class by two objects are equal  and  unequal when hashCode () values.

Source follows  (NormalHashCodeTest.java):

import java.util.*;
import java.lang.Comparable;

/**
 * @desc 比较equals() 返回true 以及 返回false时, hashCode()的值
 *
 */
public class NormalHashCodeTest{

    public static void main(String[] args) {
        // 新建2个相同内容的Person对象,
        // 再用equals比较它们是否相等
        Person p1 = new Person("eee", 100);
        Person p2 = new Person("eee", 100);
        Person p3 = new Person("aaa", 200);
        System.out.printf("p1.equals(p2) : %s; p1(%d) p2(%d)\n", p1.equals(p2), p1.hashCode(), p2.hashCode());
        System.out.printf("p1.equals(p3) : %s; p1(%d) p3(%d)\n", p1.equals(p3), p1.hashCode(), p3.hashCode());
    }

    /**
     * @desc Person类。
     */
    private static class Person {
        int age;
        String name;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String toString() {
            return name + " - " +age;
        }

        /** 
         * @desc 覆盖equals方法 
         */  
        public boolean equals(Object obj){  
            if(obj == null){  
                return false;  
            }  
              
            //如果是同一个对象返回true,反之返回false  
            if(this == obj){  
                return true;  
            }  
              
            //判断是否类型相同  
            if(this.getClass() != obj.getClass()){  
                return false;  
            }  
              
            Person person = (Person)obj;  
            return name.equals(person.name) && age==person.age;  
        } 
    }
}

Operating results :

p1.equals(p2) : true; p1(1169863946) p2(1901116749)
p1.equals(p3) : false; p1(1169863946) p3(2131949076)

Can also be seen from the results: case of equal p1 and p2, hashCode () is not necessarily equal.

2. The second would create "classes corresponding hash table"

        Here, "will create a class corresponding hash table" is to say: We will nature of these HashSet, Hashtable, HashMap, and so is the hash data structure of the list, use the class. For example, it will create a collection HashSet class.

        In this case, the class "hashCode () and equals ()" are related:
        1), if two objects are equal, then their hashCode () values be the same.
              Here means equal, it returns true if two objects by comparing equals ().
        2) If two objects hashCode () are equal, they are not necessarily equal.
               Because in the hash table, the hashCode () are equal, the hash value that is equal to two key-value pairs. However hash values are equal, not necessarily draw key-value pairs are equal. Added the sentence: "Two different key-value pairs, equal hash value," which is a hash conflict.

        Further, in this case. To determine whether two objects are equal, in addition to covering equals (), but also on covers hashCode () function. Otherwise, equals () is invalid.
For example, to create a collection of Person class HashSet, you must cover the equals Person class () and hashCode () method.
        If the coverage only just equals () method. We will find, equals () method does not achieve the results we want.

Reference code  (ConflictHashCodeTest1.java):

import java.util.*;
import java.lang.Comparable;

/**
 * @desc 比较equals() 返回true 以及 返回false时, hashCode()的值
 *
 */
public class ConflictHashCodeTest1{

    public static void main(String[] args) {
        // 新建Person对象,
        Person p1 = new Person("eee", 100);
        Person p2 = new Person("eee", 100);
        Person p3 = new Person("aaa", 200);

        // 新建HashSet对象 
        HashSet set = new HashSet();
        set.add(p1);
        set.add(p2);
        set.add(p3);

        // 比较p1 和 p2, 并打印它们的hashCode()
        System.out.printf("p1.equals(p2) : %s; p1(%d) p2(%d)\n", p1.equals(p2), p1.hashCode(), p2.hashCode());
        // 打印set
        System.out.printf("set:%s\n", set);
    }

    /**
     * @desc Person类。
     */
    private static class Person {
        int age;
        String name;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String toString() {
            return "("+name + ", " +age+")";
        }

        /** 
         * @desc 覆盖equals方法 
         */  
        @Override
        public boolean equals(Object obj){  
            if(obj == null){  
                return false;  
            }  
              
            //如果是同一个对象返回true,反之返回false  
            if(this == obj){  
                return true;  
            }  
              
            //判断是否类型相同  
            if(this.getClass() != obj.getClass()){  
                return false;  
            }  
              
            Person person = (Person)obj;  
            return name.equals(person.name) && age==person.age;  
        } 
    }
}

Operating results :

p1.equals(p2) : true; p1(1169863946) p2(1690552137)
set:[(eee, 100), (eee, 100), (aaa, 200)]

Analysis of the results :

        We rewrite the Person of equals (). However, it is strange discovery: HashSet still has repeating elements: p1 and p2. Why does this happen?

        This is because although the content p1 and p2 are equal, but their hashCode () range; therefore, HashSet add p1 and p2 of time that they are not equal.

Here, we also cover the equals () and hashCode () methods.

Reference code (ConflictHashCodeTest2.java):

import java.util.*;
import java.lang.Comparable;

/*
 * @desc 比较equals() 返回true 以及 返回false时, hashCode()的值
 *
 */
public class ConflictHashCodeTest2{

    public static void main(String[] args) {
        // 新建Person对象,
        Person p1 = new Person("eee", 100);
        Person p2 = new Person("eee", 100);
        Person p3 = new Person("aaa", 200);
        Person p4 = new Person("EEE", 100);

        // 新建HashSet对象 
        HashSet set = new HashSet();
        set.add(p1);
        set.add(p2);
        set.add(p3);

        // 比较p1 和 p2, 并打印它们的hashCode()
        System.out.printf("p1.equals(p2) : %s; p1(%d) p2(%d)\n", p1.equals(p2), p1.hashCode(), p2.hashCode());
        // 比较p1 和 p4, 并打印它们的hashCode()
        System.out.printf("p1.equals(p4) : %s; p1(%d) p4(%d)\n", p1.equals(p4), p1.hashCode(), p4.hashCode());
        // 打印set
        System.out.printf("set:%s\n", set);
    }

    /**
     * @desc Person类。
     */
    private static class Person {
        int age;
        String name;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String toString() {
            return name + " - " +age;
        }

        /** 
         * @desc重写hashCode 
         */  
        @Override
        public int hashCode(){  
            int nameHash =  name.toUpperCase().hashCode();
            return nameHash ^ age;
        }

        /** 
         * @desc 覆盖equals方法 
         */  
        @Override
        public boolean equals(Object obj){  
            if(obj == null){  
                return false;  
            }  
              
            //如果是同一个对象返回true,反之返回false  
            if(this == obj){  
                return true;  
            }  
              
            //判断是否类型相同  
            if(this.getClass() != obj.getClass()){  
                return false;  
            }  
              
            Person person = (Person)obj;  
            return name.equals(person.name) && age==person.age;  
        } 
    }
}

Operating results :

p1.equals(p2) : true; p1(68545) p2(68545)
p1.equals(p4) : false; p1(68545) p4(68545)
set:[aaa - 200, eee - 100]

Analysis of the results :

        This time, equals () in force, HashSet no duplicate elements.
        Compare p1 and P2 , we find: they hashCode () equal) by comparing them also return true equals (. So, p1 and p2 are considered equal.
        Compare p1 and P4 , we find: Although their hashCode () are equal; however, by equals () to compare their returns false. So, p1 and p4 are not considered equal.

Reprinted to : https://www.cnblogs.com/skywang12345/p/3324958.html

 

Guess you like

Origin blog.csdn.net/qq_41544550/article/details/93373909