JAVA 底层 (一) HashMap

目录

一、原理

二、扩容

三、Hashcode

四、遍历方式

五、总结汇总


HashMap 是在JAVA比较常用的一个对象,其底层实现原理 数组+链表的结构实现的(PS:jdk 8 后 变成数组+<链表/红黑树(链表元素个数大于8切换成红黑树)>)

一、原理

以下简单图为例,当一个HashMap创建时 ,会创建一个空数组 。

当使用 put()方法时,也就是添加key-value 元素进去,底层是将 key通过hashCode()方法 得到一个整数,作为数组的下标存放 元素,但当key的hashCode相同(即hash碰撞)就会在 相同的下标位置,在上一个的元素后添加,形成一个链表结构,且上一个存在元素是带有 下一个元素的指向。

当使用get()方法获取元素时,底层是拿到key的hashcode,然后通过code定位下标,再通过equla()方法判断key是否相等来获取 元素的值。

二、扩容

在使用 new HashMap< , >()时,默认的扩容系数是0.75,初始大小是16,也就是说当存在的元素数量超过12时,就会自动rehash。进行2*16(2n)一个扩容。扩容操作是非常消耗性能,会对下标重新进行分配。

三、Hashcode

HashMap的HashCode是一个散列的一个集合,对象能在里面找到一个属于自己的code,具体是通过java Hash算法 通过位运算得出。不同的对象有可能会得出相同的hashCode(碰撞)

四、遍历方式

HashMap<String,String> map=new HashMap<>();
Iterator it=map.entrySet().iterator();
while (it.hasNext()){
            Map.Entry entry= (Map.Entry) it.next();
            Object key=entry.getKey();
            Object value=entry.getValue();
        }

五、JDK1.8

HashMap 在JDK8 后 put()换成了尾部插入法,在当链表长度大于8时,链表会转换成红黑树,查询复杂度从0(n)变成0(Log n)

六、总结汇总

Hashtable的实现基本和HashMap一致,区别在hashcode生成的方式与取模,以及加了 synchronized 进行一个线程安全,所以性能略低

PS:线程不安全的原因,hashMap在数据 扩容的时候,会将链表的元素位置反转, 如果两个线程同时操作的,就会形成两个反转,形成循环锁死状态。

数组+链表结构 初始大小 扩容 扩容系数 hashCode 线程 key,value
HashMap 16 2n 0.75 位运算 不安全 可以为空
HashTable 11 2n+1 0.75 取模 安全 不可为空

猜你喜欢

转载自blog.csdn.net/qq_37203082/article/details/112624986