昨天面试的时候,面试官从线程安全的集合开始问起,然后顺便问到了hashMap的实现原理。因为之前一直不注重底层的实现,所以都只是大概看一眼,没有认真深入的去了解。今天花了一个下午的时间去看了java对hashmap的底层实现。
首先要明白hashMap是键值对存储的,允许存在空值,当它的key为空时会被存储在下标为0的table里。它是线程不安全的,这样访问速度快。
首先要说说储存的数据结构是一个数组,而这个数组的类型是用定义一个entry类来存放信息的。entry类包括key和value两个对象。同时存放一个hash值还有一个entry 的next。有点类似于链表的结点。
这边的数组给的初始长度是16还有一个加载因子,当数据达到75%时,就会扩容成原来的2倍(这边的具体还没研究透彻)
现在开始谈一谈hashMap中的put方法和get方法的实现。其实原理很简单,就是对传入的key值先做hash处理,然后再将hash和table的长度进行特定的处理后得到该entry对应存储的位置。当发生哈希冲突的时候,它会以一种链表的形式存储。此时它们算出来的数组位置是一致的,所以要存储之前需要对该位置的entry进行遍历。此时直接就比较key这个对象与链表中是否相等。若有则将对应的value值覆盖原来的。并且返回回来的值。若没有,则将这个新的entry添加到链表头,返回null.
get方法和put的原理类似,也是通过key对象查找到对应的存储位置,然后返回value对象。
这边值得一提的就是当在比较key对象是否相等是,使用的是hash和查找出来的e.hash相等,或者是直接用key==e.key,或者是key.equals(e.key)来判断。
网友评论