HashMap底层实现原理

本文主要探讨了JavaHashMap中putVal方法的内存优化、hash函数高位利用、链表转红黑树的注意事项,以及并发安全问题,特别是线程不安全的HashMap在并发环境中的操作和ConcurrentHashMap的建议使用。
摘要由CSDN通过智能技术生成

学习笔记

1.为什么在putVal方法的源码中,要将table赋给tab?

老师说:在方法中声明的tab在线程栈中,而table在堆里。从线程栈中取比堆里去要快。(JVM中的知识)

疑问:这个赋值不是引用类型的吗?tab不还是指向堆里的table?

2.为什么这里h要右移16位?

解释:

public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }


hash()

(h = key.hashCode()) ^ (h >>> 16)


putVal()

(p = tab[i = (n - 1) & hash])


在i=(n-1) & hash中,我们知道所得到的值一定是小于n的
例如:n=16,n-1=15 ,hash任意
n-1 :0000 1111
hash:1010 1001
&   :0000 1001
所得到的结果只与hash的低位有关。那么hash值的高位就没有用到。
注意,这里的hash源于hash()里面的。
所以,为了要用到hash的高位,就在hash()里面(h = key.hashCode()) ^ (h >>> 16),将hashCode的低位和它的高位进行^运算。

3.从链表变成红黑树源码的一个注意点

4.并发安全问题

代码例子:

 private static HashMap<Integer,String> map = new HashMap<Integer, String>(2,0.75f);
    public static void main(String args[]){
        map.put(5,"C");
        new Thread("Tread1"){
            public void run(){
                map.put(7,"B");
                System.out.println(map);
            };
        }.start();
        new Thread("Thread2"){
            public void run(){
                map.put(3,"A");
                System.out.println(map);
            };
        }.start();
其中,map初始化为一个长度为2的数组,loadFactor=0.75,threshold=2*0.75=1,也就是说当put第二个key的时候,map就需要resize。
(偷个懒,主要是看文档时看的一头雾水,所以做个笔记)
注意两个点,是 同时debug到transfer方法,也就是说,两个线程都已经成功添加数据。但是 都没有转移到新数组(即没有扩容)。 这里没必要太过纠结transfer方法,只需想明白,还没有扩容。
然后让线程2进行resize。
这里换了张图,会更容易理解。
注意: 纵向是顺序, 现在线程2得到调度进行扩容。
在这里假设在扩容后的新数组情况下,A-B-C还是都在同一数组下标中。但是由于JDK1.7中,是头插法,所以在线程2进行数据转移时链表顺序就会变成C——>B——>A。此时线程1又得到了调度中,因为它不知道线程2修改了B和C的关联关系,所以它的current指针和next指针还是指向B、C。 此时它会尝试将C的next指针指向B,将B设为首节点,此时B、C就形成了环。
并发场景的其他问题
                4.HashMap是线程不安全的,不要在并发的环境中同时操作HashMap,建议使用ConcurrentHashMap。
  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值