HashMap实现原理
Posted huangxy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HashMap实现原理相关的知识,希望对你有一定的参考价值。
简介
HashMap 根据键的 hashCode 进行数据的存取,大多数情况下可以直接定位到它的值,从而具有很高的效率,是无序的,要想具有顺序可用LinkedHashMap; 键值均可为null;是非线程安全的,如果需要满足线程安全,可以用Collections的synchronizedMap或者使用 ConcurrentHashMap。
JDK1.7实现
JDK1.7中HashMap采用数组+链表的实现方式,Entry 是 HashMap 中的一个内部类,他的成员变量包括:key(键)、value(值)、next(用于实现链表结构,指向下一个链表节点)、hash(存放的是当前key的hashCode)。
put方法
public V put(K key, V value) if (table == EMPTY_TABLE) //是否初始化 inflateTable(threshold); if (key == null) //放置在0号位置 return putForNullKey(value); int hash = hash(key); //计算hash值 int i = indexFor(hash, table.length); //计算在Entry[]中的存储位置 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); //添加到Map中 return null;
在添加键值对时,首先判断table是否初始化,如果没有,则进行初始化;然后判断key是否为null,如果为null,放置在Entry[]的0号位置,不为null,计算在Entry[]数组的存储位置;判断该位置上是否存在元素,如果存在,则遍历该Entry[]数组位置上的链表;判断key是否存在,如果key已经存在,则用新的value值,替换点旧的value值,并将旧的value值返回;将key-vlaue生成Entry实体,添加到HashMap中的Entry[]数组中。
get方法
public V get(Object key) if (key == null) //返回table[0] 的value值 return getForNullKey(); Entry<K,V> entry = getEntry(key); return null == entry ? null : entry.getValue(); final Entry<K,V> getEntry(Object key) if (size == 0) return null; int hash = (key == null) ? 0 : hash(key); for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) Object k; if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; return null;
首先计算hash值,然后调用indexFor()方法得到该key在table中的存储位置,得到该位置的单链表,遍历链表找到key和其对应的Entry,通过entry.value返回value值。
JDK1.8实现
在JDK1.8中,HashMap存储的数据结构由数组+链表的方式,变为数组+链表+红黑树的存储方式,提升了性能;解决了JDK1.7版在并发条件下出现死循环的问题。
问题
问:如果两个key的hashCode相同,如何获取值对象?
答:当调用get方法时,HashMap会使用key的hashCode值,找到bucket位置,因为hashCode相同,bucket会发生碰撞,然后遍历链表,通过key的equals方法找到键值对。
以上是关于HashMap实现原理的主要内容,如果未能解决你的问题,请参考以下文章