从一个并发异常问题引起的想法

79 阅读1分钟

这是我参与8月更文挑战的第25天,活动详情查看:8月更文挑战

  1.HashMap的底层:

   数组+链表/红黑树

2.几个变量和常量:

 默认的初始容量=1<<4    =>16(左移-->2的4次方;

 

 **MaxMum_capacity=1<<30  最大的容量;

(3)Default_load_Factor:默认的加载因子 0.75;

 

static final float DEFAULT_LOAD_FACTOR = 0.75f;

(4)threshold:树化阈值

  

 static final int TREEIFY_THRESHOLD = 8;

数组后面一个元素的链表的元素

是八个---就要考虑--是一个树形(查询变快;);

(5)  反树化--要是数值比6小---考虑的是变成链表;

 

static final int UNTREEIFY_THRESHOLD = 6;

树--删除成6变成-0-链表

链表多啦---元素多啦---直接是变成树;

(6)当单个链表的结点为8个,但是table的长度为64,才会树化;

当单个链表的结点为8个,但是table的长度未达到64,会扩容;

static final int MIN_TREEIFY_CAPACITY = 64;

2.JDK1.8的源码分析:

     (1)初始化:

 


 public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }

    /**
     * Constructs an empty <tt>HashMap</tt> with the default initial capacity
     * (16) and the default load factor (0.75).
     */
    public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
    
       //表示的是将加载因子设置为默认的0.75
        //其他字段都是默认值;
        
        /*
          size=0;
          table=null;
          threshold=0阈值;
          
        
        */
    
    
    }

      (2)添加的问题:

image.png

然后是开始进行put:

image.png

--创建一个默认的16的数组,

阈值为12

image.png

阈值到达12之后--增加到2倍;

\

新数组的容量是16的2倍32;

image.png

image.png

3.集合中ModCount的作用:

 每个集合中都有;

image.png

transient int modCount;\

记录的是当前集合被修改的次数:

add()或者是remove()

当自己modCOUNT的记录数和这个ExpectCount不一致-----》并发修改异常

  一个在add()    ModCount增加1;

要是不一致--直接是输出异常;

导致的currentModificationException()的并发修改异常;

记录一下并发修改异常:

image.png

如果我们想过滤出其中的对象,组成一个新的集合: 我建议使用stream流中的filter的作为过滤条件;

如果说是两个集合进行对比过滤:

我的建议是将,单个list集合转化成map; key-value,其中value是哪个对象;

接着遍历另外一个集合,从而判断出需要过滤后的新集合;