ArrayList源代码分析

2016-10-24  本文已影响0人  梦想家图图图

ArrayList类定义如下:

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable

ArrayList是基于数组实现的,容量是可以动态扩展的,初始的容量是10

private static final int DEFAULT_CAPACITY = 10;

调用默认构造函数的时候给一个空数组EMPTY_ELEMENTDATA:

public ArrayList() {
        super();
        this.elementData = EMPTY_ELEMENTDATA;
    }

ArrayList定义了两个私有属性:

private int size; //元素的数量
private transient Object[] elementData; //存储元素的数组

**transient **关键字的作用是在对象被序列化的时候属性前面修饰这个属性可以防止这个属性被序列化。


我们看构造方法

public ArrayList(int initialCapacity) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
    }

    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        super();
        this.elementData = EMPTY_ELEMENTDATA;
    }

    /**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        size = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    }
  • 第一个构造函数式构造赋值的容量的空的List
  • 第二个构造函数构造创建空数组的List
  • 第三个构造函数将提供的集合转成数组返回给elementData

add方法:

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

代码剖析:

  • ensureCapacityInternal函数判断数组elementData是空数组的话,根据初始大小10和传入的size选取最大的作为数组的最新的size,并且调用Arrays.copyOf(elementData, newCapacity)拷贝元素到新的数组中然后将元素添加到数组的最后

第二个add方法

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++;
    }

代码剖析

  • rangeCheckForAdd方法判断是否越界,如果越界抛出IndexOutOfBoundsException。
  • ensureCapacityInternal方法扩容
  • System.arraycopy将elementData从index开始的size-index个元素复制到index+1至size+1的位置
  • 将对应的值插入到index位置

addAll方法

public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

*addAll(Collection<? extends E> c)方法的作用是将传入的集合所有的元素都给添加到当前ArrayList最后。


addAll(int index, Collection<? extends E> c)

public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);

        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount

        int numMoved = size - index;
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);

        System.arraycopy(a, 0, elementData, index, numNew);
        size += numNew;
        return numNew != 0;
    }
  • addAll方法实现了从当前list的第index元素后插入传入的list,其他元素项后移动numNew个元素。

**get(int index) **方法:

public E get(int index) {
        rangeCheck(index);
        return elementData(index);
    }
  • get方法首先检查下标是否越界,如果没有越界,继续返回数组中的第index+1个元素。

clear()方法

public void clear() {
        modCount++;
        for (int i = 0; i < size; i++)
            elementData[i] = null;
        size = 0;
    }
  • clear方法调用后,list中的所有的元素都会被置为空,且size置为0.

indexOf()方法

public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }
  • 首先判断是否为null,逐个遍历,如果相等的话,就返回下标.
  • 不为空的话,使用equals方法判断是否相等,返回下标.

上一篇下一篇

猜你喜欢

热点阅读