HashMap的相关知识点总结

一.  基本概念

首先HashMap是一种常用的数据结构,由数组和链表构成,

数组里面有很多K-V的实例,在java7叫entry,在Java8叫node,

本身所有的位置都为null,在put插入的时候会根据Key的的hash值去计算一个index值

 

二.  既然HashMap是由数组和链表构成的,那么链表是如何形成的?

        不同的Key可能会通过hash函数映射为同一个index值,这样留形成了链表

 

三.  既然会形成链表,那么新的Entry节点是怎么插入的呢?

         Java8之前是头插法,也就是说新来的值会取代原有的值,

          因为最开始时认为后来的值被查找的可能性会大一些,可以提升查找效率

          但是Java8之后就是尾插法了

四.  为什么Java8之后就改为尾插法了呢?原因涉及到了HashMap的扩容机制,那HashMap的扩容机制是什么样的呢?

          首先提到HashMap是由数组和链表组成的,而数组的容量是有限的,因此到达一定的容量,就会扩容

          扩容涉及两个因素:

                               1.Capacity : HashMap的当前长度

                               2. LoadFactor : 负载因子,默认值是0.75

          也就是说,当存储容量达到Capacity*LoadFactor的时候,判断发现需要resize(扩容)

           具体实现扩容分为两步;

                                1.扩容:创建一个新的数组,长度是原来的2倍

                                 2.ReHash: 遍历原来的数组,将元素在此重新hash到新数组中

       那么为什么需要ReHash呢?是因为hash函数,与数组长度有关,当长度改变后,相应的存储位置也会改变

五.  说完尾插法会涉及到的扩容机制,那么到底是什么原因改为了尾插法,和扩容机制又有什么关系呢?

          场景例子:HashMap的数组大小是2,也就是存了1个元素,就要被扩容,假设在多线程情况下存储ABC

              头插法不扩容是这样子的: A->B->C

                                            

            头插法扩容情况下就变成了这样子:

                                          

             这个时候就看出了问题,若使用头插法,扩容之前A指B,扩容之后B指A。也就是Infinite Loop(死循环)

那么尾插法为什么不会发生死循环呢?

       是因为Java8之后链表有红黑树,除了将原本O(n)的时间复杂度变为了O(logn)外,还保持了节点之间的引用关系

六.  既然Java8之后的HashMap不会造成死循环,那么可以说它是线程安全的嘛?

        当然是不可以的,因为源码中的put/get方法没有加锁,这样就会出现同步问题,即无法保证

        上一秒put的值下一秒get到原值。

七.  源码的初始化大小是多少呢?是16,那为什么是16呢?

        因为阿里巴巴规范插件赋初值最好是2的幂,这样是为了位运算,位与运算比算数计算的效率高了很多,

        是为了实现均匀分布

八.  为什么重写equals方法时需要重写hashCode呢?

       在Java中,所有的对象都是继承于Object类,这里面有两个方法,就是equals和hashCode,这两个方法都是用来比较两个           对象是否相等的。在未重写equals方法时,比较的是两个对象的地址,在HashMap中一个node下的链表地址是相同的,那           么 久无法保证具体找到某一个元素,办法就是通过重写equals方法和hashCode方法,以保证相同的对象返回相同的hash             值,不同的对象返回不同的hash值,相同的hash值情况下还能保证hashcode的不同

九.  怎么处理HashMap的线程安全的场景?

       为保证线程安全一般要使用HashTable或者CurrentHshMap,

       HashTable简单粗暴,直接在方法上上锁,并发度很低,最多同时允许一个线程访问,

       CurrentHashMap是针对entry上的锁,这样并发度会提高很多

补充:

      本篇内容借鉴了公众号: 三太子敖丙   内容诙谐幽默,简洁明白,向大家强烈安利!!

      index的计算公式:index = HashCode(Key) & (Length- 1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值