==、equals、hashcode、hashset判重

0. 哈希码值hashCode


哈希码值(hashCode),也称散列码值是一个通过哈希散列算法得到的数据值,在java中可通过int hashCode()返回某对象的哈希码值。

这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode()函数。

hashCode有以下特点

  1. 哈希散列算法对于同一个对象在同一次程序执行过程中,调用多次hashcode方法得到的值必须是一致的;
  2. 哈希散列算法对于不同对象计算出的哈希码结果相同的概率非常小,可认为是一一对应的单射。即:每个对象的哈希码值都不同
  3. 因着以上两点可以判断两个对象是否是同一个对象。

hashCode的计算方式:

  1. 字符串:\(s[0]*31^{(n-1)}+s[1]*31^{(n-2)}+...+s[n-1]^0\)
    其中s[i]是字符串的第i个字符,n是字符串长度。空字符串的哈希值为0;
  2. 八大基本数据类型哈希值是固定:
  1. 整型:就是值本身
  2. 浮点型:通过固定的计算模式计算得到
  3. 字符型:是该字符对应的ASCII码值
  4. 布尔型:哈希值是固定的 true:1231 false:1237

 

1. ==和equals


== : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象。

  • 基本数据类型 == 比较的是值。
  • 引用数据类型 == 比较的是内存地址

equals() : 它的作用也是判断两个对象的地址是不是相等。但它一般有两种使用情况:

  • 情况1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。(object的equals方法是比较的对象的内存地址。)
  • 情况2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来两个对象的内容相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。此时,标准流程如下:
  1. 先判断地址值是否相同,同则直接true。
  2. 判断传入参数是否为null,是则直接false。
  3. 判断两个对象是否同一类型(利用getClass()),如果不是则直接false。
  4. 进行每个属性的一一判断
  1. 基本数据类型用==
  2. 引用数据类型用equals
//重写equals案例
class Person{
    String name;
    int age;
    public boolean equals(Object obj){
        if(this==obj) return true;//同一个对象
        if(obj==null) return false;//空指针
        if(this.getClass()!=obj.getClass()) return false;

        //在方法参数中向上造型了,隐蔽了其中的子类属性
        //必须要再向下造型,方可调用
        Person person = (Person)obj;

        //比较第一个属性
        if(this.name==null){
            if(person.name!=null){
                return false;
            }
        }else if(this.name.equals(person.name)){
            return false;
        }
        //比较第二个属性
        if(this.age!=person.age) return false;
        //到此为止,必然相同
        return true;
    }
}

【注】地址值实际就是该对象的哈希码值转为16进制的字符串形式。

 

2. HashCode与equals的相关规定


  1. 如果两个对象相等,则hashcode一定也是相同的。
  2. 两个对象相等,对两个对象分别调用equals方法都返回true
  3. 两个对象有相同的hashcode值,它们也不一定是相等的(虽然概率极小)
  4. hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)

 

3.【引】HashSet如何检查重复?


当把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashcode 值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。

但是如果发现有相同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就会覆盖。如果不同的话,就会重新散列到其他位置。