ArrayList就是一个可调整大小的数组,即可动态的增减元素,改变数组大小。
以下是我阅读ArrayList源码的一点心得及总结:
首先,ArrayList定义:
可以看出ArrayList是支持泛型的ArrayList<E>,继承AbstractList,实现LIst,RandomAccess, Cloneable, java.io.Serializable接口
其中LIst也是支持泛型的,定义了列表必须实现的方法。
RandomAccess是个标记接口,无内容。如果List子类实现了RandomAccess接口,那就表示它能够快速随机的访问元素。
即:ArrayList实现RandomAccess接口,意义在于访问列表时,可以选择最佳方式快速的访问。
Cloneable标识接口,无内容。实现Cloneable类,可以调用Object.clone()方法返回对象的浅拷贝。
实现java.io.Serializable接口即可启用序列化功能。
ArrayList属性,2个私有属性
elementData是ArrayList存储的元素,size是ArrayList的大小。
实现java.io.Serializable接口,将不需要序列化的属性前加上transient关键字,序列化对象时,该属性就不会被序列化到指定的目的地中。
ArrayList提供了3个构造方法以满足不同需求:
先看前2个:
第一个构造方法是根据传递的initialCapacity来初始化数组的大小,如果传递的值小于0 ,就会抛出参数不合法提示。
第二个构造方法调用第一个构造方法传入10来初始化数组,即数组大小为10.
下面来看第三个构造方法,如下:
将传递的集合转换成数组返回给elementData(返回的如果不是Object[],则调用Arrays.copyOf方法转为Object[])
Arrays.copyOf方法的具体实现:
首先是分配一个大小为newLengthd的Object,再调用系统方法arraycopy将original拷贝到copy中,从位置0开始拷贝newLength个长度,拷贝到copy中也是从位置0开始赋值,最后返回copy.
ArrayList的其他方法:
ensureCapacity(int minCapacity)方法,确保数组的最小容量
传递参数为minCapacity,用oldCapacity记下原来数组的大小,如果minCapacity的值大于原来数组大小,则需要增加容量来确保数组的容量够用。
如何增加的 呢?
使用(oldCapacity * 3)/2 + 1赋值给新的容量newCapacity,那么接下来就该判断新容量newCapacity和传递的minCapacity的大小了。如果newCapacty小于minCapacity,则说明定义的新容量太小不能满足要求,所以要把minCapacity赋值给新容量newCapacty作为原来数组的大小;否则说明新容量newCapacty大于传递的参数,可以满足要求,这样就保证来了最终的newCapacity是大于或等于传递的minCapacity的,即copy返回的最终elementData数组不会出现越界问题。
最后调用Arrays.copyOf方法把newCapacity作为数组的大小copy返回给elementData。
IndexOf()方法:
遍历数组elementData,如果传递的O在数组中存在即和某个值相等,则返回所在索引即【0,size-1】,若不存在则返回-1.
注:若存在多个,则返回第一次出现的位置(满足条件的lowest),是顺序遍历的。
与之相反的是lastIndexOf()方法:
遍历数组返回最后一次和O相等的位置,所以倒序遍历数组找第一次出现O的位置即可,并返回下标。
add(E e)在数组尾部添加元素
首先调用ensureCapacity(size+1)方法确保数组容量,上面已经解释过,调用此方法传递size+1,则数组elementData容量至少是size+1,即至少容量增加了一个,所以再给elementData[size}=e不会越界,赋值后属性size++自增1.
add(int index,E element),添加指定元素到指定位置:
首先判断传递的指定位置index是否在合理范围内【0,size】,若不满足则抛出越界异常(如果等于size,则是在数组尾端添加元素element)
调用ensureCapaCity(size+1)保证数组容量至少增加1,之后调用System.arrayCopy()方法,将数组elementData从特定位置index开始拷贝size-index个长度(即index之后的元素)到elementData数组(拷贝的元素赋值从index+1开始),换句话说就是把从index位置(如是第5个元素)后的元素全部后移一位(放到第6位),依次类推共size-index个元素直至把elementData[size-1]最后一个元素放到新的elementData[size]中,此时size还是原来的size大小。
再把指定元素放到index(第5个位置)上,即elemnetData[index]=elment;最后size自增1.
删除指定位置的元素remove(int index):
与添加指定元素到指定位置类似,RangeCheck(index)检查index是否在合理的范围内【0,size-1】
muMoved=(size-1)-index;意为需要移动的元素个数,如果要删除的是第一个位置0,则需要把size-1个元素即除去原本的第一个元素,其他所有后面的元素均要向前移动一位(这里不是真的移动,是吧后面 的index+1位置元素拷贝到index位置上,形象的理解为向前移动)。最后size--自减1,最后空出的位置赋值为null.返回删除的元素oldValue.
一点小小理解,暂时写到这。