& hashCode()和equals()的作用、区别、联系

哈希码(HashCode)

哈希码产生的依据:哈希码并不是完全唯一的,它是一种算法,让同一个类的对象按照自己不同的特征尽量的有不同的哈希码,但不表示不同的对象哈希码完全不同。也有相同的情况,看程序员如何写哈希码的算法。

在Java中哈希码代表对象的特征。
例如:

String str1 = "aa";
String str2 = "bb";
String str3 = "aa";

str1.hashCode = 3104
str2.hashCode = 3106
str3.hashCode = 3104

根据hashCode由此可得出 str1!=str2 str1==str3

下面给出几个常用的哈希码的算法:

  1. Object类的hashCode返回对象的内存地址经过处理后的结果,由于每个对象的内存地址都不一样,所以哈希码也不一样。
  2. String类的hashCode,根据String类包含的字符串的内容,根据一种特殊算法返回hashCode,只要字符串所在的堆空间相同,返回的哈希码也相同。
  3. Integer类,返回的哈希码就是Integer对象里所包含的哪个整数的数值,列如 Integer i1 = new Integer(100);,那么i1.hashCode的值就是100。因此,2哥一样大小的Integer对象,返回的哈希码也一样。

equals()

  1. 默认情况(没有重写equals方法)下equals方法都是调用Object类的equals方法,而Object的equals方法主要判断对象的内存地址引用是不是同一个地址(是不是同一个对象)。
  2. 要是类中重写了equals方法,则就要根据重写后的equals方法进行比较,一般都是通过对象的内容是否相等来判断对象是否相等。

equals()与hashCode()的比较

hashCode()和equals()一样都是基本类Object里的方法,他们作用其实一样,都是用来对比两个对象是否相等一致。

  • 那么equal()既然已经能实现对比的功能了,为什么还要hashCode()呢?
    因为:重写的equals()方法中的逻辑一般比较全面比较复杂,这样效率就很低,而利用hashCode()进行比较,则只要生成一个hash值进行比较就行了,效率很高。
  • 那么hashCode()既然效率这么高为什么还要equals()?

    因为:hashCode()并不是完全可靠的,有时候不同的对象他们生成的hashcode也会一样(生成的hash值的算法公式可能存在问题),所有hashCode()只能说是大部分时候可靠,并不是绝对可靠。

  • 结论:
    • equals()相等的两个对象他们的hashCode肯定相等,也就是用equals()比较是绝对可靠的。
    • hashCode()相等的两个对象他们的equals()不一定相等,也就是hashCode()不是绝对可靠的。
    • 因此对于需要大量并且快速的对比的话如果都用equals()去做显然效率太低,所以解决方式是,每当需要对比的时候,首先用hashCode()去对比,如果hashCode()不一样,则表示这两个对象肯定不相等(也就是不必再用equals()去再对比了),如果hashCode()相同,此时再对比他们的equals(),如果equals()也相同,则表示这两个对象是真的相同了,这样既能大大提高了效率也保证了对比的绝对正确性!
    • 一般重写了equals(),就要重写hashCode()。

hashCode()在集合中用的多

HashSet,HashMap,HashTable等等,这种大量的并且快速的对象对比一般使用的hash容器中,比如hashSet里要求对象不能重复,则他内部必然要对添加进去的每个对象进行对比,而他的对比规则就是像上面说的那样,先hashCode(),如果hashCode()相同,再用equal()验证,如果hashCode()都不同,则肯定不同,这样对比的效率就很高了。

将对象放入到集合中时,首先判断要放入对象的hashcode值与集合中的任意一个元素的hashcode值是否相等,如果不相等直接将该对象放入集合中。
如果hashcode值相等,然后再通过equals方法判断要放入对象与集合中的任意一个对象是否相等,如果equals判断不相等,直接将该元素放入到集合中,否则不放入。

img

map.put源码

public V put(K key, V value) { 
        if (key == null) 
            return putForNullKey(value); 
        int hash = hash(key.hashCode()); 
        int i = indexFor(hash, table.length); 
        for (Entry<K,V> e = table[i]; e != null; e = e.next) { 
            Object k; 
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { 
                V oldValue = e.value; 
                e.value = value; 
                e.recordAccess(this); 
                return oldValue; 
            } 
        } 

        modCount++; 
        addEntry(hash, key, value, i); 
        return null; 
}
原文地址:https://www.cnblogs.com/doagain/p/14969326.html