集合类中线程安全的就只有,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返回的仍然还是原来那个数组对象