ArrayList源码分析

来源:互联网 发布:suse yum配置 编辑:程序博客网 时间:2024/05/01 05:19

常用集合类

1. ArrayList 源码分析

ArrayList内部使用的是一个数组来保存数据. 主要是利用 Arrays.copyOf() 方法来动态扩展数组长度. ArrayList还是相对简单的.

1.1 ArrayList原理

ArrayList内部使用了一个 Object[] 来存储数据。

// 存储数据的数组private transient Object[] elementData;

ArrayList初始化时可以指定数组大小

// 指定数组大小,初始化ArrayList.public ArrayList(int initialCapacity) {    super();    if (initialCapacity < 0)        throw new IllegalArgumentException("Illegal Capacity: "+                                           initialCapacity);    this.elementData = new Object[initialCapacity];}

如果不指定大小则, 默认是空数组

// 默认空数组定义private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};// 无参数构造方法public ArrayList() {    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}

1.2 ArrayList 优化函数.

当不在添加元素时, 将剩余的空间释放掉.

public void trimToSize() {    modCount++;    if (size < elementData.length) {        elementData = (size == 0)          ? EMPTY_ELEMENTDATA          : Arrays.copyOf(elementData, size);    }}

1.3 增加元素API

默认情况下元素添加到最后一个元素的后面

public boolean add(E e) {    // 设置数组长度, 确保数组够长.如果不够会自动增加长度.    ensureCapacityInternal(size + 1);  // Increments modCount!!    // size是当前元素个数. 下面这句代码是将元素添加到最后.    elementData[size++] = e;    return true;}

下面来看下 ensureCapacityInternal 更新数组实际长度的方法.

private void ensureCapacityInternal(int minCapacity) {    modCount++;    // 判断当前数组长度是否小于数组长度. 如果不小于则增加长度.    if (minCapacity - elementData.length > 0)        grow(minCapacity);}

下面来看下 grow 方法源码.

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

上面的代码非常简单首先将数组长度增加2倍, 如果还是不够长度, 则直接将长度增加到minCapacity.之后还要比较此时长度是否超过最大长度.处理过程如下

private static int hugeCapacity(int minCapacity) {    if (minCapacity < 0) // overflow        throw new OutOfMemoryError();    return (minCapacity > MAX_ARRAY_SIZE) ?        Integer.MAX_VALUE :        MAX_ARRAY_SIZE;}

在指定位置添加元素API

public void add(int index, E element) {    rangeCheckForAdd(index);    ensureCapacityInternal(size + 1);  // Increments modCount!!    // 将要插入位置以后的元素, 整体后移.    System.arraycopy(elementData, index, elementData, index + 1,                     size - index);    // 在index位置插入.    elementData[index] = element;    size++;}

1.4 删除元素API

remove(index)

public E remove(int index) {    rangeCheck(index);    modCount++;    // 获取要删除元素值.    E oldValue = elementData(index);    // 获取要删除元素的个数.    int numMoved = size - index - 1;    // 将index 之后的元素前移    if (numMoved > 0)        System.arraycopy(elementData, index+1, elementData, index,                         numMoved);    // 将最后一个位置设置为null    elementData[--size] = null; // clear to let GC do its work    return oldValue;}

ArrayList的结构相对简单.也容易理解.

原创粉丝点击