HashMap底层实现原理

1,hashmap的数据结构
数组:查询速度快,可以根据索引查询;但插入和删除比较困难;
链表:查询速度慢,需要遍历整个链表,但插入和删除操作比较容易。
hashmap是数组和链表组成的,数据结构中又叫“链表散列”。数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entry的next指向null),那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增;对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好。
在这里插入图片描述
图中,0~12部分即代表哈希表,也称为哈希数组,数组的每个元素都是一个单链表的头节点,链表是用来解决冲突的,如果不同的key映射到了数组的同一位置处,就将其放入单链表中。
Entry数组
HashMap的主干是一个Entry数组.每一个Entry包含一个key-value键值对

//HashMap的主干数组,可以看到就是一个Entry数组,初始值为空数组{}
//主干数组的长度一定是2的次幂,至于为什么这么做,后面会有详细分析。
transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;

Entry是HashMap的一个静态内部类

static class Entry<K,V> implements Map.Entry<K,V> {
        final K key;
        V value;
        Entry<K,V> next;//存储指向下一个Entry的引用,单链表结构
        int hash;//对key的hashcode值进行hash运算后得到的值,存储在Entry,避免重复计算

        /**
         * Creates new entry.
         */
        Entry(int h, K k, V v, Entry<K,V> n) {
            value = v;
            next = n;
            key = k;
            hash = h;
        }

2hashmap特点

  1. 快速存储 :比如当我们对hashmap进行get和put的时候速度非常快
  2. 快速查找(时间复杂度o(1))当我们通过key去get一个value的时候时间复杂度非常的低,效率非常高
  3. 可伸缩:1数组扩容,边长。2,单线列表如果长度超过8的话会变成红黑树

3.hashmap的Hash算法
在聊哈算法之前我们要知道在Java中所有对象都有hashcode(使用key的),如果使用object对象get hashcode的话会得到要给int类型的指,我们在hashmap中主要是用他的key去计算它的值的。
Hash值的计算
Hash值=(hashcode)^(hashcode >>> 16)
Hashcode予hashcode自己向右位移16位的异或运算。这样可以确保算出来的值足够随机。因为进行hash计算的时候足够分散,以便于计算数组下标的时候算的值足够分散。前面说过hashmap的底层是由数组组成,数组默认大小是16,那么数组下标是怎么计算出来的呢,那就是:
数组下标:hash&(16-1) = hash%16
对哈市计算得到的hash进行16的求余,得到一个16的位数,比如说是1到15之间的一个数,hashmap会与hash值和15进行予运算。这样可以效率会更高。计算机中会容易识别这种向右位移,向左位移。
Hash冲突
不同的对象算出来的数组下标是相同的这样就会产生hash冲突。
在这里插入图片描述
Hash冲突会产生单向链表
当单线链表达到一定长度后效率会非常低,那么在jdk1.8以后的话,加入了红黑树,也就是说单线列表达到一定长度后就会变成一个红黑树
Hashmap底层原理扩容
扩容
数组长度变成2倍 0.75
触发条件
数组存储比例达到75% – 0.75

以下是需要理解的:
1,Hashmap的扩容并不是为单线链表准备的,单线链表只是为了解决hash冲突准备的。也就是说当数组达到一定长度,比如说hashmap默认数组长度是16,那么达到出发条件,数组存储比例达到了75% ,也就是16*0.75=12的时候就会发生扩容,
2,红黑树
一种二叉树,高效的检索效率

前面说了,当链表达到一定长度后,链表就会变成红黑树

触发条件
在链表长度大于8的时候,将后面的数据存在二叉树中

3,Hash算法
为什么要用hash算法。在我们Java中任何对象都有hashcode,hash算法就是通过hashcode与自己进行向右位移16的异或运算。这样做是为了计算出来的hash值足够随机,足够分散,还有产生的数组下标足够随机

4,Hash冲突
面试的时候问为什么会有hash冲突
比如说我们同样要插入一个数组,大家计算出来都是13号。那么这个时候就会产生hash冲突,为了解决hash冲突,我们的数组就会变成单线链表,然后当我们的单线链表达到一定长度的时候就产生红黑树。

更多详细请看:https://www.cnblogs.com/chengxiao/p/6059914.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路漫漫其远,吾求索

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值