Java中的hashCode方法就是根据必定的规则将与对象相关的信息(好比对象的存储地址,对象的字段等)映射成一个数值,这个数值称做为散列值,即hashCode值.html
在Java的Object类中有一个方法:java
public native int hashCode();
根据这个方法的声明可知,该方法返回一个int类型的数值,而且是本地方法,所以在Object类中并无给出具体的实现。算法
有些朋友误觉得默认状况下,hashCode返回的就是对象的存储地址,事实上这种见解是不全面的,确实有些JVM在实现时是直接返回对象的存储地址,可是大多时候并非这样,只能说可能存储地址有必定关联。数组
hashCode返回的并不必定是对象的(虚拟)内存地址,具体取决于运行时库和JVM的具体实现性能
在Java中hashCode的实现老是伴随着equals,他们是紧密配合的,你要是本身设计了其中一个,就要设计另一个。固然在多数状况下,这两个方法是不用咱们考虑的,直接使用默认方法就能够帮助咱们解决不少问题。可是在有些状况,咱们必需要本身动手来实现它,才能确保程序更好的运做。this
对于equals,咱们必须遵循以下规则:spa
对称性:若是x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。设计
反射性:x.equals(x)必须返回是“true”。code
类推性:若是x.equals(y)返回是“true”,并且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”。htm
一致性:若是x.equals(y)返回是“true”,只要x和y内容一直不变,无论你重复x.equals(y)多少次,返回都是“true”。
任何状况下,x.equals(null),永远返回是“false”;x.equals(和x不一样类型的对象)永远返回是“false”。
对于hashCode,咱们应该遵循以下规则:
1. 在一个应用程序执行期间,若是一个对象的equals方法作比较所用到的信息没有被修改的话,则对该对象调用hashCode方法屡次,它必须始终如一地返回同一个整数。
2. 若是两个对象根据equals(Object o)方法是相等的,则调用这两个对象中任一对象的hashCode方法必须产生相同的整数结果。
3. 若是两个对象根据equals(Object o)方法是不相等的,则调用这两个对象中任一个对象的hashCode方法,不要求产生不一样的整数结果。但若是能不一样,则可能提升散列表的性能。
根据hashCode,equals所遵循的规则咱们不可贵出:
若是x.equals(y)返回“true”,那么x和y的hashCode()必须相等。
若是x.equals(y)返回“false”,那么x和y的hashCode()有可能相等,也有可能不等。
能够用一张流程图来描述 hashCode,equals是如何配合使用
`
整个处理流程是:
一、判断两个对象的hashcode是否相等,若不等,则认为两个对象不等,完毕,若相等,则比较equals。
二、若两个对象的equals不等,则能够认为两个对象不等,不然认为他们相等。
对于包含容器类型的程序设计语言来讲,基本上都会涉及到hashCode。在Java中也同样,hashCode方法的主要做用是为了配合基于散列的集合一块儿正常运行,提升查找效率.这样的散列集合包括HashSet、HashMap以及HashTable
实际场景:当向集合中插入对象时,如何判别在集合中是否已经存在该对象了?(注意:集合中不容许重复的元素存在如Set集合)
解决办法:采用equals方法去逐一比较,效率必然是一个问题.此时就须要用hashcode和equals配置使用提升效率
根据第二章节hashcode,equals所遵循的规则以及配合使用的流程.
当集合要添加新的对象时,先调用这个对象的hashCode方法,获得对应的hashcode值,实际上在HashMap的具体实现中会用一个table保存已经存进去的对象的hashcode值
1. 若是table中没有该hashcode值,即第一步的判断 hashcode是否相同结果为false ,表示没有与该对象相等的对象.它就能够直接存进去,不用再进行任何比较了
2.若是存在该hashcode值,进行第二步equals判断(由于根据hashcode规则不一样对象可能具备相同的hashcode值),若是为true即对象相等,存在该对象就不保存.反之false不存在保存.
下面这段代码是java.util.HashMap的中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; }
hashCode重要么?不重要,对于List集合、数组而言,他就是一个累赘,可是对于HashMap、HashSet、HashTable而言,它变得异常重要。因此在使用HashMap、HashSet、HashTable时必定要注意hashCode。对于一个对象而言,其hashCode过程就是一个简单的Hash算法的实现,其实现过程对你实现对象的存取过程起到很是重要的做用。