先自我反思,再谈HashMap实现原理
Posted Eric余浩
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了先自我反思,再谈HashMap实现原理相关的知识,希望对你有一定的参考价值。
其实自从开始coding以来,我就自认为我完全不需要过多的了解一算法的底层实现原理,只要会用,能完成项目的需求,达到预期效果就可以了,管它怎么实现的呢.如今想想我真应该抽自己几个大嘴巴子,我怎么能这样呢,我又不是陶渊明,怎么得了不求甚解这么时髦的病了?
其实也不是我赶时髦,还是我天性懒惰,心浮气躁,没能静下心来好好coding.所以今天跑去看了HashMap的源码,记录了自己的一些理解.
至于为什么最开始看的是HashMap这部分的,是因为一方面平时用的也蛮多的,今天就是想看看大牛是怎么实现这个功能的,另一方面的确在求职面试过程中这块问到的机率还是很大的(是不是又流露出了功利主义的嘴脸),但是不管怎样代码我也是看了,文章也写咯.
HashMap用来存储Key-Value键值对的一个集合,在HashMap这个类的内部是通过Entry这个内部类来构造Key-Value的数据结构的,换句话说一个键值对就是一个Entry类的对象,这些对象是存放在一个默认长度为16的数组中.如果要一开始就修改默认长度的话,一般是改为2的n次方,至于为什么一会说.
如果添加(通过put("username","Eric")方法添加)了一个键值对那么这个键值对要存放在这个16个位置的哪一个位置呢?其实这是通过Key的哈希值经过Hash函数得到应该存放的数组的下标的
index = Hash("username")
一开始我以为这个Hash()函数是通过对Key的哈希值取模得到index的,后来看了源码才知道为了提高性能是通过位运算的方式得到index的,并且我们还希望键值对最好能均匀的分布在16个位置中,这也是数组的长度要为2的n次方的原因:
index = Key的HashCode & (数组长度-1)
如果不是2的n次方的话不能均匀的分布在数组中.还有一个问题,如果只是这样的话,那出现两个index相同怎么办,例如两个Key求出来的index都是2,都要存在数组的2号位置,怎么解决? 答案是通过链表解决,就是说数组的每一个位置存放的是一个entry的链表,这个链表采用的是头插法,(为什么是头插法,我也不知道,百度说是HashMap的设计者们认为你后添加的想让它先找到的机率应该会大一点,所以就选择了头插法)
查找就很简单了(通过get("username"))
首先是有Key ---> index 得到index都相同的一个链表,再通过HashCode找到Key为username的键值对.
还有一个平衡系数 默认为0.75 什么意思?之间讲过数组默认长的为16,但这个长度是动态改变的,当添加的Entry>16*0.75的时候长度变为16*2=32
以上是关于先自我反思,再谈HashMap实现原理的主要内容,如果未能解决你的问题,请参考以下文章