ArrayList 底层是一个对象数组:protected Object[]elementData; 无参构造: ArrayList先通过无参构造器被赋予一个空的数组elementData,初始容量为0 添加元素时执行list.add list.add中 1)先调用ensureCapacitynternal方法确定是否扩容并且向该方法传入size+1参数 ensureCapacitynternal方法用minCapacity接受了size+1参数作为此时数组需要的最小容量 先判断数组是否为空,如果为空则将一个默认初值DEFAULT_CAPACITY=10和minCapacity中的最大值赋给minCapacity,第一次赋值当然10大所以第一次minCapacity变成10 然后ensureCapacitynternal方法中调用了ensureExplicitCapacity方法 其中modCount++记录集合被修改次数(避免多线程操作异常) 再比较minCapacity和数组大小elementData数组长度,如果前者大于后者就就进行真正的扩容(通过grow方法) grow方法才是真的扩容,先将原来数组长度elementData.length赋给一个变量oldCapacity 再将一个变量newCapacity被赋予oldCapacity的1.5倍,因为第一次oldCapacity=0,所以1.5倍之后还是0所以newCapacity=0 再比较newCapacity和minCapacity比较如果前者大的话就调用Arrays.copyOf(底层其实是System.copyOf)第一次newCapacity=0所以小于minCapacity=10所以第一次扩容将minCapacity赋给newCapacity elementData = Arrays.copyOf(elementData , newCapacity); 将ArrayList维护的elementData数组容量扩大到1.5倍 然后逐步返回,最后返回到add方法 2)执行赋值elementData[size++]=e; 将要添加的变量e添加到扩容后的数组下标为size的位置中,然后下标+1 有参构造: ArrayList有参构造器的initialCapacity形参接受用户指定的的数组初始大小 并创建一个容量为initialCapacity大小的空数组 this.elementData = new Object[initialCapacity] 剩下的流程和无参构造一样 Vector 底层也是一个对象数组 protected Object[]elementData; Vector是线程安全的,操作方法带有synchronized修饰 流程大致和ArrayList一致 其中ArrayList中的ensurCapacityInternal方法被替换成了ensureCapacityHelper 其中最需要关注的的是Vector的grow扩容机制 先看Vector的构造器 其中capacityincrement是Vector的扩容因子 无参构造器:数组初始容量initialcapacity默认为10 public Vector() { this(initialcapacity:10); } 单个参数构造器:传入一个初始数组容量 public Vector(int initialCapacity) { this(initialCapacity, 0); } 双参数构造器:传入一个数组初始容量和一个扩容因子 public Vector(int initialCapacity, int capacityIncrement) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; this.capacityIncrement = capacityIncrement; } 再看Vector的grow扩容机制 private Object[] grow(int minCapacity) { int oldCapacity = elementData.length; int newCapacity = ArraysSupport.newLength(oldCapacity, minCapacity - oldCapacity, /* minimum growth */ capacityIncrement > 0 ? capacityIncrement : oldCapacity /* preferred growth */); return elementData = Arrays.copyOf(elementData, newCapacity); } private Object[] grow() { return grow(elementCount + 1); } 扩容时候先调用下面的grow再调用上面的grow通过minCapacity接受elementCount+1即所需最小的数组容量 其他和ArrayList差不多关键是下面的 capacityIncrement > 0 ? capacityIncrement : oldCapacity /* preferred growth */); 如果扩容因子为0的话就按照两倍扩容有参的就是参数的两倍,无参的就是10的两倍 有扩容因子的话就按照扩容因子大小扩容
ArrayList和Vector的扩容机制
最新推荐文章于 2022-10-16 21:25:43 发布