ArrayList介绍
List 接口的一个实现类,内部是用一个数组存储元素值,相当于一个可变大小的数组。
签名
- public class ArrayList<E>
- extends AbstractList<E>
- implements List<E>, RandomAccess, Cloneable, Serializable
- http://www.nvzi91.cn/fujianyan/29948.html
复制代码
可以看到ArrayList继承了AbstractList抽象类,它实现了List接口的大多数方法。如果要实现一个不可变的List,只要继承这个类并且实现get(int)和size方法。如果要实现可变的List,需要覆盖set(int, E)。另外,如果List的大小是可变的,还要覆盖add(int, E)和remove()方法。
构造器
ArrayList提供了三个构造器:
- ArrayList(http://www.nvzi91.cn/chunvmoxiufu/29949.html)
- ArrayList(Collection<? extends E> c)
- ArrayList(int initialCapacity)
复制代码
Collection接口约定,每个集合类应该提供两个”标准”构造器,一个是无参数的构造器(上面第一个),另外一个是拥有单个参数(类型为Collettion)的构造器(上面第二个)。ArrayList还提供了第三个构造器,其接受一个int值,用于设置ArrayLi的初始大小(默认大小为10)。
相关方法 trimToSize
- public void trimToSize() {
- modCount++;
- int oldCapacity = elementData.length;
- if (size < oldCapacity) {
- elementData = Arrays.copyOf(elementData, size);
- }http://www.nvzi91.cn/niaodaoyan/29950.html
- }
复制代码
用于把ArrayList的容量缩减到当前实际大小,减少存储容量。其中的变量modCount由AbstracList继承而来,记录List发生结构化修改(structurally modified)的次数。elementData中实际存储了ArrayList的元素,在ArrayList中声明为:private transient Object[] elementData;变量size是ArrayList的元素数量,当size < oldCapacity时,调用Arrays.copyOf方法实现缩减。
indexOf 和 lasIndexOf
- public int indexOf(Object o) {
- if (o == null) {
- for (int i = 0; i < size; i++)
- if (elementData[i]==null)
- return i;http://www.nvzi91.cn/chunvmoxiufu/29951.html
- } else {
- for (int i = 0; i < size; i++)
- if (o.equals(elementData[i]))
- return i;
- }
- return -1;
- }http://www.nvzi91.cn/yindaoyan/29952.html
复制代码
这两个方法返回指定元素的下标,要区分参数是否为null。lastIndexOf和indexOf类似,只不过是从后往前搜索。
ensureCapacity
- public void ensureCapacity(int minCapacity) {
- if (minCapacity > 0)
- ensureCapacityInternal(minCapacity);
- }http://www.kmrlyy.com/fujianyan/33465.html
- private void ensureCapacityInternal(int minCapacity) {
- modCount++;
- // overflow-conscious code
- if (minCapacity - elementData.length > 0)
- grow(minCapacity);
- }http://www.kmrlyy.com/fujianyan/33466.html
- 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);
- }http://www.kmrlyy.com/penqiangyan/33467.html
复制代码
这个方法可以确保ArrayList的大小
add 和 addAll
- public void add(int index, E element) {
- rangeCheckForAdd(index);
-
- ensureCapacityInternal(size + 1); // Increments modCount!!
- System.arraycopy(elementData, index, elementData, index + 1,
- size - index);
- elementData[index] = element;
- size++;
- }http://www.kmrlyy.com/gongjingai/33468.html
复制代码
add(int index, E element)向指定位置添加元素,首先调用rangeCheckForAdd检查index是否有效,如果index > size || index < 0将抛出异常。然后确保容量加1,调用System.arraycopy把从index开始的元素往后移动一个位置。最后把index处的值设置为添加的元素。还有一个重载的add(E e)方法是直接把元素添加到末尾。
addAll(Collection c)和addAll(int index, Collection c)则分别是向末尾和指定位置添加Collection中的所有元素。
remove 和 removeAll
- public boolean remove(Object o) {
- if (o == null) {
- for (int index = 0; index < size; index++)
- if (elementData[index] == null) {
- fastRemove(index);
- return true;
- }http://www.kmrlyy.com/gongjingai/33469.html
- } else {
- for (int index = 0; index < size; index++)
- if (o.equals(elementData[index])) {
- fastRemove(index);
- return true;
- }http://m.nvzi91.cn/gongjingfeida/29358.html
- }
- return false;
- }
复制代码
remove(Object o)方法删除指定的元素。首先是查找元素位置,然后调用fastRemove(index)删除,其代码如下:
- private void fastRemove(int index) {
- modCount++;
- int numMoved = size - index - 1;
- if (numMoved > 0)
- //把index+1往后的元素都往前移动一个位置
- System.arraycopy(elementData, index+1, elementData, index,
- numMoved);
- elementData[--size] = null; // Let gc do its work
- }http://m.nvzi91.cn/gongjingmilan/29359.html
复制代码
重载的remove(int index)方法用于删除指定位置的元素。removeRange(int fromIndex, int toIndex)用于删除指定位置之间的所有元素。
removeAll(Collection c)和retainAll(Collection c)代码如下:
- public boolean removeAll(Collection<?> c) {
- Objects.requireNonNull(c);
- return batchRemove(c, false);
- }
- public boolean retainAll(Collection<?> c) {
- Objects.requireNonNull(c);
- return batchRemove(c, true);
- }http://m.nvzi91.cn/gongjingjibing/29360.html
复制代码
它们都是通过调用batchRemove方法实现的,其代码如下:
- private boolean batchRemove(Collection<?> c, boolean complement) {
- final Object[] elementData = this.elementData;
- int r = 0, w = 0;
- boolean modified = false;
- try {www.nvzi91.c
- for (; r < size; r++)
- if (c.contains(elementData[r]) == complement)
- elementData[w++] = elementData[r];
- } finally {
- // Preserve behavioral compatibility with AbstractCollection,
- // even if c.contains() throws.
- if (r != size) {
- System.arraycopy(elementData, r,
- elementData, w,
- size - r);
- w += size - r;
- }www.kmrlyy.com
- if (w != size) {
- // clear to let GC do its work
- for (int i = w; i < size; i++)
- elementData[i] = null;
- modCount += size - w;
- size = w;
- modified = true;
- }
- }m.nvzi91.cn
- return modified;
- }
复制代码
这个方法有两个参数,第一个是操作的Collection,第二个是一个布尔值,通过设置为true或false来选择是removeAll还是retainAll。try里面的语句是把留下来的放在0到w之间,然后在finally中第二个if处理w之后的空间,第一个是在c.contains()抛出异常时执行。