干货分享丨集合框架之HashMap底层实现原理

Posted 牛耳教育Newer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了干货分享丨集合框架之HashMap底层实现原理相关的知识,希望对你有一定的参考价值。


Java的集合类是一些非常实用的工具类,主要用于存储和装载数据 (包括对象),因此,Java的集合类也被称为容器。


在Java中,所有的集合类都位于java.util包下,这些集合类主要是基于两个根接口派生而来,它们就是 Collection和 Map。


Collection & Map?

Collection表示一组对象,这些对象也称为Collection元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。JDK不提供此接口的任何直接实现,而是提供更具体的子接口实现,如 Set 和 List。此接口通常用来传递 collection,并在需要最大普遍性的地方操作这些 collection。


还有一种集合接口Map,Map集合中的元素是以键值对的形式存放的。Map 接口提供三种collection 视图,允许以键集、值集或键-值映射关系集的形式查看某个映射的内容。映射顺序定义为迭代器在映射的collection 视图上返回其元素的顺序。某些映射实现可明确保证其顺序,如 TreeMap 类;另一些映射实现则不保证顺序,如 HashMap 类。


干货分享丨集合框架之HashMap底层实现原理


01

什么是HashMap?

HashMap是基于哈希表的map接口实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。


02

HashMap实现原理

HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,然后找到bucket位置来储存值对象。


当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会储存在链表的下一个节点中。 HashMap在每个链表节点中储存键值对对象。


03

HashMap的初始化

HashMap初始容量是16,可以对其进行扩容,扩容的公式是:newsize = oldsize*2,size一定为2的n次幂。而且扩容是针对整个Map,每次扩容时,原来数组中的元素依次重新计算存放位置,并重新插入。插入元素后才判断该不该扩容,有可能无效扩容(插入后如果扩容,如果没有再次插入,就会产生无效扩容)。


当Map中元素总数超过Entry数组的75%,触发扩容操作,为了减少链表长度,元素分配更均匀。计算index方法:index = hash & (tab.length – 1)


HashMap的初始值还要考虑加载因子

  • 哈希冲突:若干Key的哈希值按数组大小取模后,如果落在同一个数组下标上,将组成一条Entry链,对Key的查找需要遍历Entry链上的每个元素执行equals()比较。

  • 加载因子:为了降低哈希冲突的概率,默认当HashMap中的键值对达到数组大小的75%时,即会触发扩容。因此,如果预估容量是100,即需要设定100/0.75=134的数组大小。

  • 空间换时间:如果希望加快Key查找的时间,还可以进一步降低加载因子,加大初始大小,以降低哈希冲突的概率。


TIPS:



以上是关于干货分享丨集合框架之HashMap底层实现原理的主要内容,如果未能解决你的问题,请参考以下文章

Java 集合框架—— HashMap

系统运维系列 之HashMap底层实现原理和应用

ListSet集合系列之剖析HashSet存储原理(HashMap底层)

Java集合之HashMap

Java集合:HashMap底层实现和原理(源码解析)

JavaMap集合,HashMap,LinkedHashMap,HashTable,Hashmap底层的原理