JDK源码(二十三):HashMap

Posted jdkSpring

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK源码(二十三):HashMap相关的知识,希望对你有一定的参考价值。

java.util.HashMap实现Map接口。此实现提供所有可选的映射操作,并允许null值和null键。(HashMap类大致等同于Hashtable,只是它不同步并且允许空值。)这个类不保证映射的顺序;特别是,它不保证顺序随时间保持不变。
Has h Map为基本操作(get和put)提供恒定的时间性能,假设哈希函数在存储桶之间正确地分散元素。集合视图上的迭代需要与HashMap实例的“容量”(bucket的数量)加上其大小(键值映射的数量)成比例的时间。因此,如果迭代性能很重要的话,不要设置太高的初始容量(或者太低的负载系数)。
HashMap的一个实例有两个影响其性能的参数:初始容量和负载因子。容量是哈希表中的存储桶数,初始容量只是创建哈希表时的容量。负载因子是在哈希表的容量自动增加之前允许获得的满容量的度量。当哈希表中的条目数超过负载因子和当前容量的乘积时,哈希表将重新hash(即重建内部数据结构),以便哈希表具有大约两倍的存储桶数。
一般来说,默认加载因子(0.75)在时间和空间成本之间提供了一个很好的折中。较高的值会减少空间开销,但会增加查找成本(反映在HashMap类的大多数操作中,包括get和put)。在设置初始容量时,应考虑map中的预期条目数及其负载系数,以尽量减少rehash操作次数。如果初始容量大于最大条目数除以负载系数,则不会发生rehash操作。

哈希表

哈希表是由一块地址连续的数组空间构成的,其中每个数组都是一个链表,数组的作用在于快速寻址查找,链表的作用在于快速插入和删除元素,因此,哈希表可以被认为就是链表的数组。


哈希冲突

多个 Key 对象,通过计算得到了同一个 的情况。
h1 =hash(key1)&(length -1)
h2 =hash(key2)&(length -1)
h3 =hash(key3)&(length -1)
如果出现下面的情况,就是冲突了
h1 == h2 == h3

解决冲突的一般办法

  • 再哈希法:首先定义很多hash函数,当发生哈希冲突时,就再使用另一个hash函数计算另一个哈希值,直到不冲突为止。

类名

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable

变量(部分)

JDK源码(二十三):HashMap

方法(JDK1.8)

put(K key, V value)

  1. 对key的hashCode()做hash,然后再计算index;

  2. 如果没碰撞直接放到bucket里;

  3. 如果碰撞了,以链表的形式存在buckets后;

  4. 如果碰撞导致链表过长(大于等于TREEIFY_THRESHOLD),就把链表转换成红黑树;

  5. 如果节点已经存在就替换old value(保证key的唯一性)

  6. 如果bucket满了(超过load factor*current capacity),就要resize。

在jdk1.8版本后,java对HashMap做了改进,在链表长度大于8的时候,将后面的数据存在红黑树中,以加快检索速度。关于红黑树,读者可另行查看,太烧脑了。

JDK源码(二十三):HashMap

resize()

初始化或加倍表大小。如果为空,则根据字段阈值中保留的初始容量目标进行分配。然而又因为我们使用的是2次幂的扩展(指长度扩为原来2倍),所以,元素的位置要么是在原位置,要么是在原位置再移动2次幂的位置。

JDK源码(二十三):HashMap

get(Object key)
  1. bucket里的第一个节点,直接命中;

  2. 如果有冲突,则通过key.equals(k)去查找对应的entry,若为树,则在树中通过key.equals(k)查找;若为链表,则在链表中通过key.equals(k)查找。

HashMap实现多线程

Map map = Collections.synchronizedMap(new HashMap<>());

以上是关于JDK源码(二十三):HashMap的主要内容,如果未能解决你的问题,请参考以下文章

面渣逆袭:HashMap追魂二十三问

我的jdk源码(二十三):ReentrantLock类

JDK源码(二十四):HashSet

JDK源码阅读之 HashMap

Spring源码分析(二十三)BeanFactory的后处理

向下之旅(二十三):模块