java jdk1.7版本的HashMap原理解析

HashMap是一个key-value集合,每一个key对应一个值,key不可以重复,对相同的key进行设值将会把原来的值进行覆盖。HashMap的底层实现原理是利用一个数组和多个单向链表实现的一个数据集合,数组的每个数据项就是一个单向链表(实际上是通过一个个Entry实例连接起来,Entry有一个next变量指向下一个元素),数组里的每个存放数据的位置我们称为桶。当要put一个键值对进去集合时,首先将会对键值对的键的hashcode进行一定的运算,运算出来是一个int类型的数据,HashMap将会根据这个int类型的数据对应到数组的一个下标,然后利用新增的键值对创建一个Entry的实例,最后把这个Entry实例加到这个下标对应的单向链表中,后加入的Entry实例将会在单向链表的前面。首先我们直观的看下HashMap数据存储结构:
这里写图片描述

Entry数据结构:
这里写图片描述

HashMap的特点:
(1)、HashMap实现了Map接口,其具有Map所有的操作;
(2)、HashMap的key和value都允许设置null值;
(3)、HashMap存放的数据是乱序的,迭代的时候不会根据存入的顺序进行迭代,也不会根据key进行排序迭代;
(4)、HashMap不是线程安全的,如果要创建一个线程安全的HashMap,可以这样创建:
Map m = Collections.synchronizedMap(new HashMap(…));
(5)、HashMap的迭代器 iterator 方法返回的迭代器是快速失败 的。所谓快速失败,意思就是如果在迭代器已经创建了的情况下,任何时刻对HashMap结构的修改,迭代器将会抛出一个ConcurrentModificationException异常。其原理是HashMap中维护了一个变量modCount,代表修改的次数,当创建迭代器时,会把这个变量保存到迭代器实例的expectedModCount变量中,在迭代的过程中会把迭代器保存的expectedModCount与modCount对比,如果发现不相等就抛出异常。如下面代码中迭代器已经生成,但是还往HashMap添加数据,那么此后的迭代过程是会抛出ConcurrentModificationException异常:
这里写图片描述

HashMap的变量说明:
(1)、table:HashMap里利用这个变量保存了整个HashMap的数据,其是一个Entry的数组:
这里写图片描述

(2)、size:HashMap中实际保存数据的数量,每put一个键值对增加1,每remove一个键值对减1。

HashMap方法实现细节:
put(K key, V value)方法,执行流程:
(1)、首先检测table变量是否已经初始化完成,如果没有初始化,则根据参数初始化table变量,实际上完成的事情是创建一个具有长度的数组;
(2)、检测传入的key是否为null,如果为null,则调用putForNullKey方法把键值对放到table数组下标为0的位置,否则进行下一步;
(3)、根据key的hashCode运算出一个int类型的数据,根据这个int类型数据调用indexFor方法找到新增的键值对应该放到table的那个下标的桶下;
(4)、根据找到的下标寻找是否该key已经在HashMap中,如果在,则更新旧值,并把旧值返回,否则进行下一步;
(5)、调用addEntry方法,判断HashMap是否需要扩容,如果需要,则把table扩充为原来的两倍。否则创建一个Entry实例,加入到对应下标的链表中。

代码截图:
这里写图片描述

这里写图片描述

这里写图片描述

get(Object key)方法,执行流程:
(1)、首先判断传入的key是否为null,如果为null,则调用getForNullKey获取key为null的值,否则进行下一步;
(2)、调用getEntry方法,根据key获取到对应的实例,获取逻辑跟put方法的逻辑类似,即首先根据key获取到table数组的下标,然后根据key对比获取到对应的Entry实例;
(3)、根据返回的实例返回实例的值。

代码截图:
这里写图片描述

这里写图片描述

这里写图片描述

HashMap与Hashtable的区别:
HashMap与Hashtable的底层实现原理一样,数据结构也一样,都是利用数组和单向链表实现。主要的区别有以下几点:
(1)、Hashtable是线程安全的,其方法都加了synchronized修饰;而HashMap不是线程安全的;
(2)、Hashtable的key和value都不允许为null,而HashMap允许;
(3)、hashMap去掉了HashTable 的contains方法,但是加上了containsValue和containsKey方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乐观男孩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值