1.Hashmap的用法
haspmap的一般用法如上图,包含key和value。
Q:但是上述的默认用户没有设置容量,hanhmap是如何创建容量的?
A:看Hashmap的源码
这里说,容量必须是2的幂数,然后设置的是左移四位,即16。
Q:为什么会用左移运算(数据都是转换成2进制来读,越接近底层,操作速度会快)
A:Java的底层是C,C的底层是汇编语言,汇编下就是机器语言(2进制),越接近底层效率越高。
Q:为什么是16,而不是4或8?
A:ava的底层是C,C的底层是汇编语言,汇编语言编程使用16进制。联想:Java中的访问修饰符是16进制(ox00001)。
2.Hashmap的核心思想
Hashmap由数组+链表+红黑树(JDK1.8)组成。红黑树是自平衡的二叉树的查找树,其特点之一是:右子树的值比节点大,左子树的值比节点小;
Node是存入Hashmap的类,其结构如下:
Node implement Map.Entry{
hash
key
value
next
}
Entry{
K key
V value
}
Node类实现Entry接口,hash值是根据key值计算出(有个hash算法),next可以联系c++中的链表结构。
Q:如何定位到数组
将key值和value值封装到node对象中,在根据所计算出的hash值和数组(length-1)的值进行位与(&)计算,得到0~length-1之间的索引,即要存入的数组位置。
3.哈希碰撞(冲突)
说明:计算出的索引位置仅与二进制的后四位有关,会有相同的索引值,相同索引值的元素如何存储,就是哈希碰撞问题。
解决方法:
jdk7通过链表解决,当有相同值时就下挂一个链表;jdk8通过红黑树,当下挂元素小于等于6时变为链表;
4.Hashmap的扩容
Q:Hashmap是如何进行扩容操作的,扩容后是如何做到数据均匀分布的?
源码中有关于扩容的方法resize()。
当数组中所占用的容量达到:扩容因子(0.75)*length时,数组的长度会左移一位,即在原长度的基础上增倍。例如,长度为16的hashmap在被占用12个单位时,会扩容成32。
A:通过高位的“奇偶数”解决均匀分布问题,当高位为1时移到索引值为(原索引+length)处,依次判断链表(或红黑树)的高位值,依次重新排布位置,以链表形式举例如下图: