HashMap源码分析(1)

HashMap源码分析(1)

一、HashMap的基本概念

  • HashMap是基于哈希表的Map接口的实现,并容许null键和null值的插入。
  • HashMap是无序的。
  • HashMap是典型的兼顾时间-空间两者的结构,接下来会探讨这方面的原因。
  • 同样的HashMap是线程不安全的,这里建议使用HashTable、ConcurrentHashMap。但是如果你不想为了百分之一的可能性去浪费内存而必须去使用HashMap,那么官方给出如下的解决方案
Map m = Collections.synchronizedMap(new HashMap(...));
  • 但是经过测试使用上述代码,在多个线程同时对一个HashMap进行修改,会抛出异常,结果是无可预知的,从而导致修改失败,所以不建议使用这个方式。

二、HashMap的存储结构

大家都知道HashMap的存储结构是基于key-value的,但是有没有想过多个key-value结构在整个内存中是怎么分布的。其实当有这个疑问的时候只需要再往下一步就可以知道了HashMap内部的存储结构。
这里写图片描述
上图就是HashMap的存储结构,是数组加链表结构。蓝色部分是哈希表,也称为哈希数组,数组的每一个元素都是单链表的头节点,链表是用来解决哈希冲突的,不同key映射到数组相同位置就会存储在数组这一位置后的单链表中,哈希冲突这点会在接下来的源码讲解中详细介绍。
众所周知,数组的存储方式在内存的地址是连续的,是大小固定的,一旦分配不能被其他所引用。特点是查询快捷,插入和删除等操作较慢。链表的存储方式是大小不固定、不连续的,特点与数组相反,查询较慢,插入删除等操作较快。在这两者角度上可以说HashMap是一种折中的解决方案。

三、HashMap的基本操作原理

1.put(key,value)
  1. 首先判断key值是否为空,如果为空那么就直接对数组的第一个元素进行查找,如果当前位置存在值,那么对该值进行替换,如果不存在值,那么直接把value放入该数组第一位。
  2. 当key不为空时,对key值进行两次hash计算,得到一个int型的Hash值,用这个Hash值对数组的长度进行取余,得到的就是该key值对于这个数组映射到的索引。
  3. 找到该数组索引下的位置,如果数组这个位没有值,那么就把value放入数组的该位置。如果有值就将值替换。在这里有一点要特别注意的事情,就是key值转换到哈希值是通过哈希算法进行转化的。我们希望一个key值对应一个哈希值从而对应到数组的唯一位置,但是很不幸的是哈希算法是没有办法做到这一点的。也就是说不同的key值有可能通过哈希计算成同一个值,我们把这个现象称为哈希冲突。为了解决这一点,这就使用到了链表结构,当不同的key值映射到数组中的同一位置时,那么就把值放入这一数组元素后的单链表中。这也称为链地址法
2.get(key)
  1. get方法基本流程也跟上述流程相同。如果key为空,那么直接返回数组的第一个元素。
  2. 当key不为空时,对key值进行两次hash计算,得到一个int型的Hash值,用这个Hash值对数组的长度进行取余,得到的就是该key值对于这个数组映射到的索引。
  3. 返回数组对应的位置下的值,如果存在链表,那么取相同的key值的value返回。

现在关于HashMap的基本原理和内部结构已经讲解的很详细了,接下来在(2)中就是上源码解析怎么去实现HashMap的了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值