综合这几天网上查资料以及查看HashMap的源码,谈谈个人对HashMap底层的理解:
HashMap是一个散列集合,其底层是数组+链表结构,主体部分是个长度很长的数组.
结构 :
主体 : Entry数组(实际存key,value的对象);
链表 : 通过next方法指向链表下一个结点
- 为了保证HashMap增删改查的效率,实质并上不是直接以key实例对象作为标识进行存值和取值,从put方法源码可以发现底层是获取key的hashCode值,经过异或运算和indexFor()方法运算得到的值作为标识,但由于hashCode的值并不唯一,经过运算获取的值也不能保证唯一(哈希冲突),所以,经过以上运算得来的数值只能作为数组的索引,当通过索引定位到这个节点时,在遍历该链表,判断是否存在相同的key对象,如果存在就用新的value覆盖旧的value
//HashMap部分源码
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null)
return putForNullKey(value);
int hash = hash(key);
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;
}
}
final int hash(Object k) {
int h = hashSeed;
if (0 != h && k instanceof String) {
return sun.misc.Hashing.stringHash32((String) k);
}
h ^= k.hashCode();
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
hasCode知识点补充
一、hasCode概念
hashCode是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值,对象通过调用hashCode()方法返回该对象的哈希码值。支持此方法是为了提高哈希表的性能。
二、作用
对于包含容器类型的程序设计语言来说,基本上都会涉及到hashCode。在Java中也一样,hashCode方法的主要作用是为了配合基于散列的集合(无序集合)一起快速正常运行,使用hashCode的价值在于速度:运用hashCode作为标识使得查询得以快速进行.
三、使用: 拿String举例
同一个对象
public void test01(){ String str1 = new String("123"); String str2 = str1; int code1 = str1.hashCode(); int code2 = str2.hashCode(); System.out.println(code1); ----->48690 System.out.println(code2); ----->48690 System.out.println(str1.equals(str2)); ----->true }
不同对象,相同内容
public void test02(){ String str1 = new String("aaa"); String str2 = new String("aaa"); int code1 = str1.hashCode(); int code2 = str2.hashCode(); System.out.println(code1); ----->96321 System.out.println(code2); ----->96321 System.out.println(str1.equals(str2)); ----->true }
- 不同字符串对象,相同内容,生成的hashCode相同,明显String里面hashCode()方法明显是根据字符串内容生成的
- 想要使hashCode()更实用,它必须速度更快,并且必须有意义,也就是说,它必须基于String对象的内容生成hashCode
- 两个字符串对象用equals()方法比较返回true,因为String类重写了equals()方法,使得内容相同的两个字符串进行比较会返回true
不同对象,不同内容
public void test03(){ String str1 ="Aa"; String str2 ="BB"; int code1 = str1.hashCode(); int code2 = str2.hashCode(); System.out.println(code1); ---->2112 System.out.println(code2); ---->2112 System.out.println(str1.equals(str2)); ---->false }
- hashCode不必是独一无二的,更应该关注生成速度,而不是唯一性.