建议对照源码食用
1.ArrayList中的3个数组:
1)Object[] EMPTY_ELEMENTDATA={},所有ArrayList实例对象共享的空数组,创建一个ArrayLis实例对象的且指ArrayList容量为0 的时候,创建实 例将会指向这个共享实例;
2)Object[] DEDAULTCAPACITY_EMPTY_ELEMENTDATA={},带有默认容量的数组实例,这个数组决定了第一次想ArrayList添加元素的时候,ArrayList中的数组容量应该要增长到多少,此处的数组和 1)中的数组是有区别的,如果向第一个元素数组添加元素,会数组下标越界的异常,第二个数组表面上虽然是空的,但是可以添加元素,不会报错
3)Object[] elementData : 被transient修饰 不可被序列化,java源码中说这是一个缓存数组,ArrayList的容量就是这个缓存数组的length,队ArrayList中的元素进行增删查该的时候,实际操作的就是这个这个数组,如果一个空的ArrayList实例中的elementData指向了DEDAULTCAPACITY_EMPTY_ELEMENTDATA,当第一次添加元素的时候,这个缓存数组的容量将会扩展到ArrayList定义默认容量的大小
2.ArrayList的默认容量:DEFAULT_CAPACITY=10; 比较保险的情况下ArrayList中最多可以存放的元素个数(size):MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8,在源码中给出的解释是一些虚拟机可能会在数组中存储一些header words;如果好需要存放更多数据,最大容量就是Integer的最大值。
3.创建ArrayList实例的时,如果明确指定了ArrayList的大小,elementData会指向一个新的数组实例,数组的长度的就是调用者给定的长度,如果指定长度为0,elementData就指向所有实例共享的空数组(是不带默认容量的空数组),不在创建新的对象;如果不指定ArrayList的长度,elementData将会指向带默认容量的共享数组
public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
..........
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
4. ArrayList中容量动态变化,ArrayList存储数据归根结底使用的是数组,对元素进行增删的时候也要需要进行扩容、缩容、数组元素迁移等操作,每次添加元素的时候都会进行判断,添加一定个数的元素的时候,会将添加元素有缓存数组(elementData)中的元素个数是否超过了缓存数组的的长度,如果超过,进行扩容,扩容之后数组长度是之前数组的1.5倍。
.....
private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } ..... private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); }
5.增删改查:
1)添加:add(E),指定位置插入元素add(int index,element e),数组迁移的时候用的的是System.arraycopy(elementData, index, elementData, index + 1,size - index);
2)删除:remove(),可以根据数组元素的index进行删除,也可以给定具体元素进行删除,index从0 开始
3)修改:set(int index,E element)
4) 查询 : get(int index) public修饰的,可以在外部调用,而element(int index)方法是缺省的,只有同一个包中的类可以访问。
原文:https://www.cnblogs.com/hurro/p/13030392.html