前言:容器是java中尤为重要的章节,都是实现一个map的接口,key-value这样的数据结构常用于内存存放数据,接下来我就跟着源码讲解hashmap!
1.首先们先打开Hashmap的源码
java版本的更新
首先我们先讲讲jdk1.7的hashmap
在jdk1.7中hashmap底层是数组+链表的结构:
上面源码中比较核心的几个源码代表的含义:
(1)static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
因为底层是数组结构,所以底层定义一个数组默认的大小为16
(2)static final int MAXIMUM_CAPACITY = 1 << 30;
桶的最大值
(3)static final float DEFAULT_LOAD_FACTOR = 0.75f;
负载因为默认为0.75
在这儿述说下负载因子,由于给定的hashmap的默认容量大小为16,负载因子为0.75,map在使用过程中,不断往容器里面存放数据,当16*0.75=12时,就会产生一个动态扩容机制,而这个动态扩容机制会涉及到rehash和复制数据等操作,所以非常影响性能,因此通常建议预估hashmap的大小,这样尽量减少性能的损耗!
继续往下面走
Entry是HashMap中的一个内部类,从他的成员变量很容易看出:
key:就是写入的键
value:自然就是值
开始的时候我们就提到1.7版本中底层结构是数据和链表组成,所以这个next就是实现链表结构,hash存放的是当前key的hashcode
我们现在大概了解数据结构和源码解析,我们在继续了解一下写入和获取函数:
put()的方法
(1)判断当前数组是否需要初始化
(2)如果key为空,则put一个值进去
(3)根据key计算hahcode
(4)根据hashcode定位所在的桶
(5)如果桶是一个链表则需要遍历判断里面的hashcode、key是否和传入的key相等,如果相等则进行一个覆盖操作,并返回原来的值
(6)如果桶是空的,说明当前位置没有数据存入,新增一个Entry对象写入当前位置
这就是put的过程
下面就是get()的方法
(1)首先也是根据key计算hashcode,然后定位到具体的桶中
(2)判断该位置是否为链表
(3)不是链表就根据key,key的hashcode是否相等来返回值
(4)为链表则需要遍历直到key及hashcode相等就返回值
(5)啥也没找到 就返回null
以上就是jdk1.7中的比较重要的一些知识点
接下来就是jdk1.8
jdk1.8对hashmap优化的一个点就是查询效率
因为在1.7中当hash冲突严重时,在桶上形成的链表会越来越长,这样的查询效率就会越来越低
其实1.7和1.8的差别不大
之间的差别为别为:HashEntry修改为Node和链表转换为红黑树的阙值
有一个resize包含的扩容操作!