Java的Object类中有一个hashCode()方法:

public final native Class<?> getClass();
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
hashCode()是一个native方法,意味着方法的实现和硬件平台有关,默认实现和虚拟机有关,对于有些JVM,hashCode()返回的就是对象的地址,大多时候JVM根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,并返回。
例如:HotSpot JVM中生成hash实现:hotspot/src/share/vm/runtime/synchronizer.cpp
 
在Java中,hashCode()方法的主要作用是为了配合基于散列的集合(HashSet、HashMap)一起正常运行。当向集合中插入对象时,调用equals()逐个进行比较,这个方法可行却效率低下。因此,先比较hashCode再调用equals()会快很多。下面这段代码是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;
}

indexFor()源码如下:

static int indexFor(int h, int length) {
return h & (length-1);
}

因为hashMap要求Entry数组长度必须为2的幂(hashMap默认值为16,hashTable没有这个要求,默认值为11),所以上述代码就是取h的低4位作为Entry数组的下标。由于覆盖equals()需要覆盖hashCode(),所以hashCode()有时并不十分完美,比如只和高位有关等等,因此需要再次hash()一下。

hash()方法在JDK1.7中如下:

static int hash(int h) {
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}

这样设计保证了对象的hashCode的32位值只要有一位发生改变,整个hash()返回值就会改变,高位的变化会反应到低位里。

具体分析参考:http://www.iteye.com/topic/709945

https://www.zhihu.com/question/20733617

hash()方法在JDK1.8中如下:

static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

这样设计保证了对象的hashCode的高16位的变化能反应到低16位中,相比较而言减少了过多的位运算,是一种折中的设计。

Java中hashCode()方法以及HashMap()中hash()方法的更多相关文章

  1. 【java基础 13】两种方法判断hashmap中是否形成环形链表

    导读:额,我介绍的这两种方法,有点蠢啊,小打小闹的那种,后来我查了查资料,别人都起了好高大上的名字,不过,本篇博客,我还是用何下下的风格来写.两种方法,一种是丢手绢法,另外一种,是迷路法. 这两种方法 ...

  2. hashmap的hash方法源doc解读

    /** * Computes key.hashCode() and spreads (XORs) higher bits of hash * to lower. Because the table u ...

  3. list中会直接绑定HashMap中的数据

    import java.util.ArrayList;import java.util.HashMap;import java.util.List; public class HashMapSync ...

  4. hashCode及HashMap中的hash()函数

    一.hashcode是什么 要理解hashcode首先要理解hash表这个概念 1. 哈希表 hash表也称散列表(Hash table),是根据关键码值(Key value)而直接进行访问的数据结构 ...

  5. [ 转载 ]hashCode及HashMap中的hash()函数

    hashCode及HashMap中的hash()函数   一.hashcode是什么 要理解hashcode首先要理解hash表这个概念 1. 哈希表 hash表也称散列表(Hash table),是 ...

  6. java中hashcode和equals的区别和联系

    HashSet和HashMap一直都是JDK中最常用的两个类,HashSet要求不能存储相同的对象,HashMap要求不能存储相同的键. 那么Java运行时环境是如何判断HashSet中相同对象.Ha ...

  7. Java中ArrayList,Vector,LinkedList,HashMap,HashTable,HashSet对比及总结

    1.所有的集合的父类都是Collection的接口 2.Set List Map 区别 A  在Set里面:无法添加元素的顺序,所以Set里面的元素不能重复 B  在List中:有索引号,类似于数组, ...

  8. 【转】【java源码分析】Map中的hash算法分析

    全网把Map中的hash()分析的最透彻的文章,别无二家. 2018年05月09日 09:08:08 阅读数:957 你知道HashMap中hash方法的具体实现吗?你知道HashTable.Conc ...

  9. 关于HashMap中hash()函数的思考

    关于HashMap中hash()函数的思考 JDK7中hash函数的实现   static int hash(int h) { h ^= (h >>> 20) ^ (h >&g ...

随机推荐

  1. HttpUtility.UrlEncode 和 HttpUtility.Encode 一个大深坑

    进行了 Encode 之后 在解码(UrlEncode )之后 + 号莫名的变成了空格, 需要执行一个replace 操作

  2. VMnet1和V8

    vmware默认使用了两个虚拟网卡: vmnet1 v1 vmnet8 v8 vmnet1是host-only,也就是说,选择用vmnet1的话就相当于VMware给你提供了一个虚拟交换机,仅将虚拟机 ...

  3. array_fill 用给定的值填充数组

    转自:http://www.phpstudy.net/php/165.html PHP array_fill 用给定的值填充数组 array_fill (PHP 4 >= 4.2.0, PHP ...

  4. 【翻译】Tomcat 6.0 部署与发布

    本篇参考Tomcat官方文档:<First Webapp>翻译,并结合自己的开发经验介绍关于tomcat部署以及发布的相关内容. 1 目录结构 在tomcat中所有的应用都是放置在CATA ...

  5. 【C语言入门教程】4.6 指针 和 数组

    数组在内存中以顺序的形式存放,数组的第一个存储单元的地址即数组的首地址.对一维数组来说,直接引用数组名就能获得该数组的首地址.指针变量可以存放于其内容相同的数组首地址,也可以指向某一具体的数组元素.通 ...

  6. java遍历map的四种方式

    在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都 ...

  7. hash-2.hashMap

    1.HashMap的数据结构 a.HashMap是一个链表散列的结合体,即,数组和链表的结合体. b.HashMap类中定义了Entry类型的数组,Entry [ ] ,Entry有key value ...

  8. ajax验证登录注册

    <form id="form1" onsubmit="return false;"> <table id="login-table& ...

  9. UOJ52——【UR #4】元旦激光炮

    1.题目大意:就是给你三个数组啦,然后让你找到其中的第K大,但是,不可以直接访问数组,必须通过一种函数,最后的分数 是看调用几次这个函数,100次以内10分,2000以内6分.... 2.分析:最开始 ...

  10. jQuery中的checkbox问题

    一开始的代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...