关于ArrayList,vector,LinkedList

集合类中线程安全的就只有,vector,hashtable,concurrentHashmap

ArrayList的初始容量为10,这里我们主要了解一下ArrayList的扩容机制

当我们一个一个添加的时候,size就会每加一个就扩容一次

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 在size=10的时候就会开始扩充了,第一次扩充到15,就不用每次加一这样扩容了
        //这里看到ArrayList添加元素的实质就相当于为数组赋值
        elementData[size++] = e;
        return true;
}
//得到最小扩容量
 private void ensureCapacityInternal(int minCapacity) {
      if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
              // 获取默认的容量和传入参数的较大值
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
      }

      ensureExplicitCapacity(minCapacity);
 }
//判断是否需要扩容
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//版本号增加
        if (minCapacity - elementData.length > 0)
            //调用grow方法进行扩容,调用此方法代表已经开始扩容了
            grow(minCapacity);
    }
    //扩容的核心算法
    private void grow(int minCapacity) {
        // oldCapacity为旧容量,newCapacity为新容量
        int oldCapacity = elementData.length;
        //将oldCapacity 右移一位,其效果相当于oldCapacity /2,
        //我们知道位运算的速度远远快于整除运算,整句运算式的结果就是将新容量更新为旧容量的1.5倍,
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //然后检查新容量是否大于最小需要容量,若还是小于最小需要容量,那么就把最小需要容量当作数组的新容量,
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;//没有超过的话就按定义的最大容量
        //再检查新容量是否超出了ArrayList所定义的最大容量,
        //若超出了,则调用hugeCapacity()来比较minCapacity和 MAX_ARRAY_SIZE,
        //如果minCapacity大于MAX_ARRAY_SIZE,则新容量则为Interger.MAX_VALUE,否则,新容量大小则为 MAX_ARRAY_SIZE。
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
//minCapacity:所需要的最小容量
    public void ensureCapacity(int minCapacity) {
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            ? 0
            : DEFAULT_CAPACITY;
        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
    }

总结的话就是,每次扩容到1.5倍。这样效率会增加很多哦

关于ArrayList的克隆的问题:

其中的源码:

/**
     * 返回此ArrayList实例的浅拷贝。 (元素本身不被复制。) 
     */
    public Object clone() {
        try {
            ArrayList<?> v = (ArrayList<?>) super.clone();
            //Arrays.copyOf功能是实现数组的复制,返回复制后的数组。参数是被复制的数组和复制的长度
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // 这不应该发生,因为我们是可以克隆的
            throw new InternalError(e);
        }
    }

其中基本上可以算是深复制了,已经重新生成了ArrayLIst了,但是ArrayList里面的元素实际上是浅复制,这是因为copyof返回的仍然还是原来那个数组对象

猜你喜欢

转载自www.cnblogs.com/smallJunJun/p/10530615.html