数据结构面试专题详解,收藏一下吧

本文详细探讨了HashMap的put、get操作以及处理hash冲突的方法。解释了当两个对象hashcode相同,HashMap如何存储键值对,并描述了HashMap的扩容机制。此外,还对比了HashMap与HashTable、ArrayMap的区别,分析了ConcurrentHashMap的实现原理,以及ArrayList和LinkedList的不同应用场景。文章适合准备数据结构和面试的开发者阅读。
摘要由CSDN通过智能技术生成

至于为什么要扩容,如果不扩容,HashMap中数组处的链表会越来越长,这样查找效率就会大大降低。

6.1 HashMap如何put数据(从HashMap源码角度讲解)?

当我们使用put(key, value)存储对象到HashMap中时,具体实现步骤如下:

  • 先判断table数组是否为空,为空以默认大小构建table,table默认空间大小为16

  • 计算key的hash值,并计算hash&(n-1)值得到在数组中的位置index,如果该位置没值即table[index]为空,则直接将该键值对存放在table[index]处。

  • 如果table[index]处不为空,说明发生了hash冲突,判断table[index]处结点是否是TreeNode(红黑树结点)类型数据,如果是则执行putTreeVal方法,按红黑树规则将键值对存入;

  • 如果table[index]是链表形式,遍历该链表上的数据,将该键值对放在table[index]处,并将其指向原index处的链表。判断链表上的结点数是否大于链表最大结点限制(默认为8),如果超过了需执行treeifyBin()操作,则要将该链表转换成红黑树结构。

  • 判断HashMap中数据个数是否超过了(最大容量*装载因子),如果超过了,还需要对其进行扩容操作。

6.2 HashMap如何get数据?

get(key)方法获取key的hash值,计算hash&(n-1)得到在链表数组中的位置first=table[hash&(n-1)],先判断first(即数组中的那个)的key是否与参数key相等,不等的话,判断结点是否是TreeNode类型,是则调用getTreeNode(hash, key)从二叉树中查找结点,不是TreeNode类型说明还是链表型,就遍历链表找到相同的key值返回对应的value值即可。

6.3 当两个对象的hashcode相同,即发生碰撞时,HashMap如何处理

当两个对象的hashcode相同,它们的bucket位置相同,hashMap会用链表或是红黑树来存储对象。Entry类里有一个next属性,作用是指向下一个Entry。第一个键值对A进来,通过计算其key的hash得到index,记做Entry[index]=A。一会又进来一个键值对B,通过计算其key的hash也是index,HashMap会将B.next=A, Entry[index]=B.如果又进来C,其key的hash也是index,会将C.next=B, Entry[index]=C.这样bucket为index的地方存放了A\B\C三个键值对,它们能过next属性链在一起。数组中存储的是最后插入的元素,其他元素都在后面的链表里。

6.4 如果两个键的hashcode相同,如何获取值对象?

当调用get方法时,hashmap会使用键对象的hashcode找到bucket位置,找到bucket位置后,会调用key.equals()方法去找到链表中正确的节点,最终找到值对象。

6.5 hashMap如何扩容

HashMap默认负载因为是0.75,当一个map填满了75%的bucket时,和其他集合类一样,将会创建原来HashMap大小两倍的bucket数组,来重新调整HashMap的大小,并将原来的对象放入新的bucket数组中。

在jdk1.7及以前,多线程扩容可能出现死循环。因为在调整大小过程中,存储在某个bucket位置中的链表元素次序会反过来,而多线程情

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值