ArrayList实现原理及源码浅析

ArrayList的实现原理

ArrayList底层是用一个数组实现的。

Object[] elementData;

当elementData装满元素时,会通过扩容的方式来增加elementData的容量

image-20200913140207567

浅析ArrayList源码

添加元素

添加元素最常用的是boolean add(E e)方法,它实际上调用的是将元素插入的指定位置的方法void add(int index, E element)。

所以我们只需要搞懂void add(int index, E element)就可以了

public void add(int index, E element) {
    rangeCheckForAdd(index);	// 检查插入的位置是否超出数组范围
    modCount++;
    final int s;
    Object[] elementData;
    if ((s = size) == (elementData = this.elementData).length)	// 判断是否需要扩容
        elementData = grow();	// 扩容
    System.arraycopy(elementData, index,	// 将目标位置上及其后面的所有元素向后移动一位,如下图所示
                     elementData, index + 1,
                     s - index);
    elementData[index] = element;	// 把要插入的元素放到目标位置
    size = s + 1;
}

private void rangeCheckForAdd(int index) {
    if (index > size || index < 0)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

例如add(2, 9)的执行流程如下

image-20200913142529879

删除元素
public E remove(int index) // 删除指定位置上的元素

该方法的源码如下,可以看到是通过调用fastRemove(es, index)来删除元素的;

public E remove(int index) {
    Objects.checkIndex(index, size);
    final Object[] es = elementData;

    @SuppressWarnings("unchecked") E oldValue = (E) es[index];
    fastRemove(es, index);

    return oldValue;
}

fastRemove实现如下:

private void fastRemove(Object[] es, int i) {
    modCount++;
    final int newSize;
    if ((newSize = size - 1) > i)
        System.arraycopy(es, i + 1, es, i, newSize - i); // 将目标位置后面的所有元素前移一位
    es[size = newSize] = null;
}

例如fastRemove(array, 2):

image-20200913143425075

public boolean remove(Object o) // 删除元素o第一出现的位置

源码如下, 可以看到是先找到元素位置,再调用fastRemove删除

public boolean remove(Object o) {
    final Object[] es = elementData;
    final int size = this.size;
    int i = 0;
    found: {
        if (o == null) {
            for (; i < size; i++)
                if (es[i] == null)
                    break found;
        } else {
            for (; i < size; i++)
                if (o.equals(es[i]))
                    break found;
        }
        return false;
    }
    fastRemove(es, i);
    return true;
}
修改元素

修改元素的源码如下,比较简单

public E set(int index, E element) {
    Objects.checkIndex(index, size);
    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}
查找元素
public E get(int index) // 查找指定位置上的元素

源码如下,比较简单

public E get(int index) {
    Objects.checkIndex(index, size);
    return elementData(index);
}

E elementData(int index) {
    return (E) elementData[index];
}
public int indexOf(Object o) // 查找元素第一次出现的位置

源码如下

public int indexOf(Object o) {
    return indexOfRange(o, 0, size);
}

indexOfRange的源码如下, 也比较简单,就是通过for循环遍历素组,找到该元素后立即返回该元素的位置,如果遍历完还没找到则返回-1

int indexOfRange(Object o, int start, int end) {
    Object[] es = elementData;
    if (o == null) {
        for (int i = start; i < end; i++) {
            if (es[i] == null) {
                return i;
            }
        }
    } else {
        for (int i = start; i < end; i++) {
            if (o.equals(es[i])) {
                return i;
            }
        }
    }
    return -1;
}
public int lastIndexOf(Object o) // 查找元素最后一次出现的位置

源码如下

public int lastIndexOf(Object o) {
    return lastIndexOfRange(o, 0, size);
}

lastIndexOfRange实现如下, 就是从数组的尾部向前遍历,找到该元素后立即返回该元素的位置,如果遍历完还没找到则返回-1

int lastIndexOfRange(Object o, int start, int end) {
    Object[] es = elementData;
    if (o == null) {
        for (int i = end - 1; i >= start; i--) {
            if (es[i] == null) {
                return i;
            }
        }
    } else {
        for (int i = end - 1; i >= start; i--) {
            if (o.equals(es[i])) {
                return i;
            }
        }
    }
    return -1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值