理解ArrayList源码

本文详细解析了ArrayList的内部实现机制,包括其动态扩容策略、初始化过程、序列化方式及迭代器实现等。并探讨了ArrayList适用于哪些场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ArrayList是使用频率较高的容器,实现较为简单。内部主要靠一个可自动扩容的对象数组来维持

transient Object[] elementData;// 非私有简化嵌套类访问

可以通过构造函数指定初始容量,也可以不指定(默认初始容量为10);

	//指定初始容量
	public ArrayList(int initialCapacity) {
       if (initialCapacity > 0) {
           this.elementData = new Object[initialCapacity];
       } else if (initialCapacity == 0) {
           this.elementData = EMPTY_ELEMENTDATA;
       } else {
           throw new IllegalArgumentException("Illegal Capacity: "+
                                              initialCapacity);
       }
   }
   //使用默认容量,在首次进行add时进行扩容
   public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

当每次通过add添加元素时会调用ensureCapacityInternal(size + 1);

private void ensureCapacityInternal(int minCapacity)
{
	//判断是否使用默认容量且为首次添加元素,计算需扩容大小
	if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
	{
		minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
	}
	//确认需要扩容的容量大于数组长度
	ensureExplictCapacity(minCapacity);
}
	//扩容机制
	private void grow(int minCapacity)
	{
		int oldCapacity = elementData.length;
		int newCapacity = oldCapacity + oldCapacity >> 1;
		if (newCapacity - minCapacity < 0)
		{
			newCapacity = minCapacity;
		}
		if (newCapacity - MAX_ARRAY_SIZE > 0)
		{
			hugeCapacity(newCapacity);
		}
		elementData = Arrays.copyOf(elementData, newCapacity);
	}

可以看出,当容量不足时,ArrayList1.5倍扩容,当使用addAll(Collection<? extends E> c)添加时,若1.5倍扩容不满足时,则使用size+c.toArray().length扩容。

ArrayList支持指定位置的赋值,通过set(int,E)和add(int,E)方法,在执行这些操作时都需要对范围进行检查,同理还有获取和移除指定位置的元素。

elementData数组是transient的,这表明系统默认序列化执行时跳过该数组。取而代之的是,ArrayList提供了writeObject和readObject方法来自定义写入和读取该数组的方式。为什么不使用elementData来序列化,因为elementData的长度通常大于size,这样做是为了确保只序列化实际存储的元素

	private void writeObject(ObjectOutputStream s) 
		throws IOException
	{
		int exceptedModCount = modCount;
		s.defaultWriteObject();
		s.writeInt(size);
		for (int i = 0; i < size; i++)
		{
			s.writeObject(elementData[i]);
		}
		if (modCount != exceptedModCount)
		{
			throw new ConcurrentModificationException();
		}
	}
	private void readObject(ObjectInputStream s) throws IOException,
			ClassNotFoundException
	{
		elementData = EMPTY_ELEMENTDATA;
		s.defaultReadObject();
		s.readInt();
		if (size > 0)
		{
			ensureCapacityInternal(size);
			Object[] a = elementData;
			for (int i = 0; i < size; i++)
			{
				a[i] = s.readObject();
			}
		}
	}

作为容器的共性,ArrayList提供迭代器,并通过内部类定义了Itr、ListItr这两个迭代器。
ArrayList的排序

	public void sort(Comparator<? super E> c) {
        final int expectedModCount = modCount;
        Arrays.sort((E[]) elementData, 0, size, c);
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }

ArrayList底层为数组,在随机添加、插入和删除,需要对元素进行移动效率低,但是对于随机访问效率很高;适用于访问多,对元素操作少的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值