当前位置: 首页 > 后端技术 > Java

HashMapvsLinkedHashMap

时间:2023-04-01 14:06:19 Java

通过各种教材,我们可以总结出HashMap和LinkedHashMap的区别:LinkedHashMap可以保持顺序,HashMap不能保持顺序。没有区别,速度快,哈希值不冲突。下一步已经到位。其实对于大部分的应用场景,我们只需要记住第一个区别即可。如果一个场景需要按照数据存储的顺序获取数据,那么我们一定要记住不能使用HashMap,必须使用LinkedHashMap。本着二手程序员的精神,我们假设您一定想知道为什么。所以我们还是从两者的底层数据结构开始分析。再分析一下两者的底层数据结构现在假设我们将如下数据依次放入HashMap和LinkeHashMap中:hm.put("李四","45");/**节点1**/hm.put("张三","20");/**节点2**/hm.put("赵六","70");/**节点3**/hm.put("Wangwu","30");/**节点4**/我们希望在保存上述数据时,用下图来说明HashMap和LinkeHashMap的数据结构。当然,我们只是为了说明问题。哈希桶是随机分配的,实际分配的哈希桶一定不是这样的。我们假设HashMap在节点1存储时得到的哈希桶是table[3],所以节点1就放在这个桶中。节点2得到的哈希桶是table[1],假设节点3和节点2的哈希值冲突,也放入table[1]。节点4放在表[15]中。通过前面两节的分析,我们知道在LinkedHashMap中存储数据的算法与在HashMap中存储数据的算法基本相同,所以在表数组中的位置,即得到的哈希桶是相同的。不同的是LinkedHashMap的表数组中存储的对象是双向链表结构。通过before和after指针记录上一个节点和下一个节点。上图简单明了地反映了结构。需要注意的是,LinkedHashMap采用双向链表结构记录所有节点,而不管是否发生哈希冲突。HashMap和LinkHashMap处理哈希冲突的方式相同:数据会被放在同一个桶中,并使用单项链表(next指向下一个节点)结构进行记录。当然你可以这样理解,HashMap(包括LinkedHashMap)的表数组只保留没有哈希冲突的数据,哈希冲突后的数据不存储在表数组中,但其他数据都可以通过表中的对象找到表数组冲突对象。HashMap为什么不能保序通过上面的分析,答案已经很明显了,我们再来说说。第一点是:HashMap存储数据时,其在表数组中的存储位置是由数据键值的哈希值决定的,而不是按顺序存储在表数组中,因此存储是乱序的。如果你现在不得不在脑海中问这样一个问题:为什么不按顺序存储它们而不是散列它们呢?那我只能弱弱的回答一下,HashMap具有取数据快的特点……第二点:HashMapkey-value遍历算法依次遍历表数组,跳过空桶。结合上面第一、二点和结构图,应该很明显HashMap是不能保持顺序的。为什么LinkedHashMap可以保持顺序第一点:LinkedHashMap通过表数组和双向链表来保存数据,链表结构保持了存储顺序。第二点:LinkedHashMap遍历键值算法是从头到尾遍历链表。所以我们也可以看出LinkedHashMap不需要遍历空桶,是真正的遍历,效率更高。结合第一点、第二点和结构图,很明显LinkeHashMap在遍历键值时可以保持顺序。对了,LinkedHashMap这种表数组加双向链表的结构,可以实现:快速顺序遍历(使用双向链表),快速定位(通过表数组,hash算法)。真的太NB了。就是这样,经过一段时间的深入研究,关于HashMap的问题就可以挂断面试官了。