2019.7.11 HashMap的工作原理?

HashMap基于hashing原理,通过put()和get()存储和获得对象。
put(),调用hashCode()获得hashcode,然后找到bucket位置来储存值对象
get(),通过键对象的equals()方法找到正确的键值对,然后返回值对象

(1)什么叫bucket?
当系统开始初始化 HashMap 时,系统会创建一个长度为 capacity 的 Entry 数组,这个数组里可以存储元素的位置被称为“桶(bucket)”,每个 bucket 都有其指定索引,系统可以根据其索引快速访问该 bucket 里存储的元素。

  • capacity为当前HashMap的Entry数组的大小,Entry数组的大小是2的N次方
  • threshold为HashMap的size最大值,注意不是HashMap内部数组的大小。
    threshold = (int)(capacity * loadFactor);
    在这里插入图片描述 存储示意

(2)什么是负载因子(load factor)
当创建 HashMap 时,有一个默认的负载因子(load factor),其默认值为 0.75,这是时间和空间成本上一种折衷:增大负载因子可以减少 Hash 表(就是那个 Entry 数组)所占用的内存空间,但会增加查询数据的时间开销,而查询是最频繁的的操作(HashMap 的 get() 与 put() 方法都要用到查询);减小负载因子会提高数据查询的性能,但会增加 Hash 表所占用的内存空间。

(3)HashMap的碰撞问题
不同的键对象有相同的hashcode值时,会发生碰撞,使用单向链表解决碰撞问题。它们会储存在同一个bucket位置的链表中。
当冲突发生时,使用某种探查技术在散列表中形成一个探查(测)序列。沿此序列逐个单元地查找,直到找到给定的地址。
按照形成探查序列的方法不同,可将开放定址法区分为线性探查法二次探查法双重散列法等。

(4)HashMap 的读取实现
当 HashMap 的每个 bucket 里存储的 Entry 只是单个 Entry ——也就是没有通过指针产生 Entry 链时,此时的 HashMap 具有最好的性能:当程序通过 key 取出对应 value 时,系统只要先计算出该 key 的 hashCode() 返回值,在根据该 hashCode 返回值找出该 key 在 table 数组中的索引,然后取出该索引处的 Entry,最后返回该 key 对应的 value 即可。如果发生了碰撞问题,单个 bucket 里存储的不是一个 Entry,而是一个 Entry 链,系统只能必须按顺序遍历每个 Entry,直到找到想搜索的 Entry 为止——如果恰好要搜索的 Entry 位于该 Entry 链的最末端(该 Entry 是最早放入该 bucket 中),那系统必须循环到最后才能找到该元素。

原文链接:https://blog.csdn.net/wenyiqingnianiii/article/details/52204136

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章