ArrayList 系统详解

  • ArrayList 是最常用的 List 实现类,它适合随机查找和遍历,但不适合插入和删除。
  • Vector 和 ArrayList 一样,但Vector 不支持线程同步,但线程安全,ArrayList 线程不安全

ArrayList 非线程安全,底层是一个 Object[ ] ,添加到ArrayList中的数据保存在了elementData属性中。所以 ArrayList 具有数组的查询速度快的优点以及增删速度慢的缺点。

  • 当调用new ArrayList<>()时,将一个空数组{}赋值给了 elementData,这个时候集合的长度size为默认长度0;
  • 当调用new ArrayList<>(100)时,根据传入的长度,new一个Object[100]赋值给 elementData,当然如果玩儿的话,传了一个0,那么将一个空数组{}赋值给了elementData;
  • 当调用 new ArrayList<>(new HashSet()) 时,根据源码,我们可知,可以传递任何实现了Collection接口的类,将传递的集合调用 toArray() 方法转为数组内赋值给elementData;

ArrayList常用方法

ArrayList有很多常用方法,add,addAll,set,get,remove,size,isEmpty等

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

首先通过 ensureCapacityInternal(size + 1) 来保证底层 Object[ ] 数组有足够的空间存放添加的数据,然后将添加的数据存放到数组对应的位置上,我们看一下是怎么保证数组有足够的空间?

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
	modCount++;
	// overflow-conscious code
	if (minCapacity - elementData.length > 0)
		grow(minCapacity);   // 数组扩容
}

首先确定 Object[] 足够存放添加数据的最小容量,然后通过 grow(int minCapacity) 来进行数组扩容

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

扩容规则为⚠️:数组当前足够的最小容量 * 1.5,有最大值限制。

set(int index, E element)

由于 ArrayList 底层由数组实现,set实现非常简单,

public E set(int index, E element) {
    rangeCheck(index);

    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}
get(int index)

ArrayList 中 get 方法也非常简单,通过下表查找即可,前提是需要判断传入的数组下标是否越界。

public E get(int index) {
    rangeCheck(index);

    return elementData(index);
}
E elementData(int index) {
    return (E) elementData[index];
}
remove(int index)

首先获取待删除的元素,并最终返回。其次计算了需要移动的位数 size - index - 1,然后将原本位置的元素设为 null

public E remove(int index) {
    rangeCheck(index);   // 判断数组越界

    modCount++;
    E oldValue = elementData(index);

    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index, numMoved);
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}
remove(Object o)

删除 ArrayList 中的值对象,其实和通过下标删除很相似,遍历底层数组 elementData ,通过 equals() 方法或 == (特殊情况)来找到要删除的元素,获取其索引值,一样的方式删除

public boolean remove(Object o) {
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                fastRemove(index);
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}
private void fastRemove(int index) {
    modCount++;
    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work
}

其他方法

size() : 获取集合长度,通过定义在ArrayList中的私有变量size得到

isEmpty():是否为空,通过定义在ArrayList中的私有变量size得到

contains(Object o):是否包含某个元素,通过遍历底层数组elementData,通过equals或==进行判断

clear():集合清空,通过遍历底层数组elementData,设置为null

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值