ArrayList

ArrayList 源码分析

构造函数

/**
 * The minimum amount by which the capacity of an ArrayList will increase.
 * This tuning parameter controls a time-space tradeoff. This value (12)
 * gives empirically good results and is arguably consistent with the
 * RI's specified default initial capacity of 10: instead of 10, we start
 * with 0 (sans allocation) and jump to 12.
 */
private static final int MIN_CAPACITY_INCREMENT = 12;

/**
 * The number of elements in this list.
 */
int size;

/**
 * The elements in this list, followed by nulls.
 */
transient Object[] array;

上面是在ArrayList类内部的重要的(仅有的)变量,根据API我们可以知道:MIN_CAPACITY_INCREMENT是指扩容时每次增加的容量,默认为12,在前几个版本的ArrayList中默认的无参数的构造函数是直接赋予了默认大小的,默认大小为10,但是在现在的版本中这种方式已经被废弃了。size是指list中元素的个数,array是指存储所有元素的数组。

接下来看下构造函数:

    public ArrayList(int capacity) {
        if (capacity < 0) {
            throw new IllegalArgumentException("capacity < 0: " + capacity);
        }
        array = (capacity == 0 ? EmptyArray.OBJECT : new Object[capacity]);
    }

    public ArrayList() {
        array = EmptyArray.OBJECT;
    }

    public ArrayList(Collection<? extends E> collection) {
        if (collection == null) {
            throw new NullPointerException("collection == null");
        }

        Object[] a = collection.toArray();
        if (a.getClass() != Object[].class) {
            Object[] newArray = new Object[a.length];
            System.arraycopy(a, 0, newArray, 0, a.length);
            a = newArray;
        }
        array = a;
        size = a.length;
    }

当构造参数为空或为0时,将EmptyArray.OBJECT赋予array,参数不为空时,参数小于0抛出异常,大于0时新建一个相同大小的Object数组。使用继承了Collection接口的子类对Array初始化时,使用collection的toArray方法将array数组赋值.

常用方法

add
/**
 * Adds the specified object at the end of this {@code ArrayList}.
 *
 * @param object
 *            the object to add.
 * @return always true
 */
@Override public boolean add(E object) {
    Object[] a = array;
    int s = size;
    if (s == a.length) {
        Object[] newArray = new Object[s +
                (s < (MIN_CAPACITY_INCREMENT / 2) ?
                 MIN_CAPACITY_INCREMENT : s >> 1)];
        System.arraycopy(a, 0, newArray, 0, s);
        array = a = newArray;
    }
    a[s] = object;
    size = s + 1;
    modCount++;
    return true;
}

在末尾插入指定对象:如果超过array数组容量,则进行扩容,如果原数组size小于6,新建数组size大小为 原size + 12,否则新建数组size为1.5倍的原size,然后将原数组内东西拷贝到新建数组中,并将新建数组赋值给array。如果array数量未超过数组容量,则直接将新增对象塞到数组尾部。 返回true。

/**
 * Inserts the specified object into this {@code ArrayList} at the specified
 * location. The object is inserted before any previous element at the
 * specified location. If the location is equal to the size of this
 * {@code ArrayList}, the object is added at the end.
 *
 * @param index
 *            the index at which to insert the object.
 * @param object
 *            the object to add.
 * @throws IndexOutOfBoundsException
 *             when {@code location < 0 || location > size()}
 */
@Override public void add(int index, E object) {
    Object[] a = array;
    int s = size;
    if (index > s || index < 0) {
        throwIndexOutOfBoundsException(index, s);
    }
    if (s < a.length) {
        System.arraycopy(a, index, a, index + 1, s - index);
    } else {
        // assert s == a.length;
        Object[] newArray = new Object[newCapacity(s)];
        System.arraycopy(a, 0, newArray, 0, index);
        System.arraycopy(a, index, newArray, index + 1, s - index);
        array = a = newArray;
    }
    a[index] = object;
    size = s + 1;
    modCount++;
}


private static int newCapacity(int currentCapacity) {
        int increment = (currentCapacity < (MIN_CAPACITY_INCREMENT / 2) ?
                MIN_CAPACITY_INCREMENT : currentCapacity >> 1);
        return currentCapacity + increment;
    }

与上一方法类似,这个add方法参数有两个,插入的对象和指定的位置,实现的操作是将指定对象插入到Arraylist指定位置,注释中说明此方法在位置小于0或位置大于list的size时抛出越界异常。新建合适大小的数组,为了防止造成空间浪费,我们使用扩容的策略新建数组(上面已经介绍过),通过System.arraycpy方法将原数组进行分割粘贴处理然后给新数组赋值。然后将新数组赋值给array,最后将插入位置赋值。

get
@SuppressWarnings("unchecked") @Override public E get(int index) {
                if (index >= size) {                throwIndexOutOfBoundsException(index, size);
                }
                return (E) array[index];
            }

如果传入的数值大于array的长度,抛出越界错误,否则返回数组array中指定位置的对象。

set
@Override public E set(int index, E object) {
        Object[] a = array;
        if (index >= size) {
            throwIndexOutOfBoundsException(index, size);
        }
        @SuppressWarnings("unchecked") E result = (E) a[index];
        a[index] = object;
        return result;
    }

将ArrayList某位置的元素进行设置,先进行判断,如果无越界则修改array数组的对应位置。

remove
@Override public E remove(int index) {
        Object[] a = array;
        int s = size;
        if (index >= s) {
            throwIndexOutOfBoundsException(index, s);
        }
        @SuppressWarnings("unchecked") E result = (E) a[index];
        System.arraycopy(a, index + 1, a, index, --s - index);
        a[s] = null;  // Prevent memory leak
        size = s;
        modCount++;
        return result;
    }

指定位置删除:删除也是先进行越界判断,如果没有异常就通过Sysytem.arrarycopy进行处理。

@Override public boolean remove(Object object) {
        Object[] a = array;
        int s = size;
        if (object != null) {
            for (int i = 0; i < s; i++) {
                if (object.equals(a[i])) {
                    System.arraycopy(a, i + 1, a, i, --s - i);
                    a[s] = null;  // Prevent memory leak
                    size = s;
                    modCount++;
                    return true;
                }
            }
        } else {
            for (int i = 0; i < s; i++) {
                if (a[i] == null) {
                    System.arraycopy(a, i + 1, a, i, --s - i);
                    a[s] = null;  // Prevent memory leak
                    size = s;
                    modCount++;
                    return true;
                }
            }
        }
        return false;
    }

指定对象删除:遍历array数组,寻找是否有与制定对象equal的对象,如果有就将array内,从指定对象的下一个位置开始的所有对象依次向前移动一位,覆盖掉要删除的对象,然后将array最后一个位置置空删除。参数可以是null。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值