Java的HashMap知识点回顾
前言
HashMap是一个被人说烂了但又很重要的知识点,同时它又相对比较简单,我的第一篇博客就拿它下手做一下回顾和总结。
正文
结构及参数
HashMap由数组+链表实现,jdk1.8后加入红黑树。
jdk1.8中HashMap的一些重要参数:
- 默认初始长度:DEFAULT_INITIAL_CAPACITY = 1<<4 = 16,HashMap的默认容量;
- 默认负载因子:DEFAULT_LOAD_FACTOR = 0.75f,表示当HashMap中的元素数量达到容量*0.75时触发扩容;
- 树化阈值:TREEIFY_THRESHOLD = 8,表示当链表的长度增至8时链表会转化为红黑树;
- 链化阈值:UNTREEIFY_THRESHOLD = 6,表示当红黑树的size降至6时红黑树转化为链表;
- 最小数形化阈值:MIN_TREEIFY_CAPACITY = 64,表示当HashMap的容量>MIN_TREEIFY_CAPACITY时才会进行链表的树化,否则当桶内元素过多的时候,会先进行扩容,而非树化。容量>MIN_TREEIFY_CAPACITY的判断在treeifyBin(Node<K,V>[] tab, int hash)方法中而不是putVal方法;
- 最大容量: MAXIMUM_CAPACITY = 1 << 30,HashMap的最大容量;
HashMap的实现结构
数组+链表就可以实现一个哈希表,1.7及之前的jdk版本中HashMap也是采用的这种结构实现,但是在面对一些极端的特殊情况时,如当插入的所有节点的K经过hash后得到的元素桶标(这里我们把数组中每个元素称为一个桶)都相同,那岂不是HashMap直接就变成了一个单链表,查询效率也会大大降低。
为了优化HashMap在链表过长时查询效率低下的问题,jdk在1.8引入了红黑树,红黑树是一种自平衡的二叉查找树,查询效率对比链表高很多。关于红黑树的工作原理,以及如何创建一个红黑树,我会在后续文章中详细说明。
HashMap是怎样计算插入元素桶标的
我们用n表示HashMap的当前容量,即桶的总个数。
用k表示新插入节点的K。
我们先思考一下如果我自己设计会怎么实现:
int index = k.hashCode() % n;
用n对k.hashCode()取余好像已经可以满足条件
1、可以使index完全落在0~n-1
2、容量不变的情况下,index的值只与k有