HashMap的分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012031408/article/details/79162967

1、了解一下hashMap的基本特性:

 1>访问速度快,但顺序不确定。

 2>允许value为null,最多允许一条记录的key为null。

 3>非线程安全。

2、hashMap的内部结构

数据结构中通常通过数组和链表两种方式来存储数据。

数组存储的特点:连续的,内存占用严重,查找容易,插入和删除困难

链表存储的特点:离散的,内存占用较宽松,查找困难,但插入和删除容易

而HashMap的内存结构实现了数组+链表+红黑树(红黑树是在jdk1.8之后增加的)


从源码中可知,hashMap默认的数组长度是16,默认的负载因子是0.75。所以HashMap默认的能容纳的键值对个数threshold=capacity * loadfactor

3、hashMap的存取实现

hashMap实现散列存储,是通过key的hash值与数组的长度取模来获取在数组中存取的下标:

//不管是jdk7还是jdk8,都是这种逻辑,只是实现的方法不同
int hash = key.hashCode();
//在jdk8中换成了Node[]数组 
int index = hash % Entry[].length;
Entry[index] = value;
4、hashMap的存储

 如果不同的key经过上面的计算得到的index相同,会不会有覆盖的危险?

不会,hashMap的接口是数组+链表,这里就使用到了链表的概念了。

在HashMap中实现了一个静态内部类Entry,该类又三个重要的属性:key,value,next。Entry就是hashMap键值对实现的一个基础bean,

所有的map数据都保存在Entry[]数组中。

第一个键值A进来,通过计算得到的数组下标为1,保存Entry[1]=A。然后B进来,计算得到的下标也是1,这时候就会记做:B.next=A,Entry[1]=B

如果再来一个,就会记做:C.next=B ,Entry[1]=C。我们发现下标为1的地方其实存储了3个键值对,他们之间通过next属性链接在一起,形成一个链表。

这个链表的长度默认是8,当链表的长度大于等于8的时候,在jdk8中,会将链表转换成红黑树。同时,我们也知道了,对于hashMap来说,数组中存储

的是最后插入的元素

5、hashMap的扩容

当存储的键值对个数超过了threshold默认的存储数量,hashMap就开始扩容

本质上就是使用一个容量更大的数组来替换已有的小容量的数组,然后在将原有的数据拷贝到新的数组中,数组的容量变大了,

相对的hashMap能容纳的键值对也会变大。



猜你喜欢

转载自blog.csdn.net/u012031408/article/details/79162967