ArrayList源码分析

1. ArrayList初始化

  • ArrayList是线性数据结构,底层实现是数组,默认capacity为10
  • 提供了2种构造方法:
    带capacity参数,立即初始化数组大小;
    不带capacity参数,引用指向一个空数组。
package java.util;

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    private static final int DEFAULT_CAPACITY = 10;
    private static final Object[] EMPTY_ELEMENTDATA = {};
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    transient Object[] elementData; // non-private to simplify nested class access
    private int size;
    
    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);
        }
    }

    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    ....
}

2. 添加元素

  • 添加元素前,判断是否需要扩容
  • 元素个数等于数组长度,进行扩容,否则存入数组,元素个数自增
  • 默认扩大1.5倍,oldCapacity >> 1,带符号右移操作为正数,位运算是出于效率考虑
	// 添加元素具体实现,当元素个数等于数组长度,会进行扩容grow操作
    private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length)
            elementData = grow();
        elementData[s] = e;
        size = s + 1;
    }

    public boolean add(E e) {
        modCount++;
        add(e, elementData, size);
        return true;
    }
    
    // 扩容具体实现,默认扩大1.5倍(oldCapacity + (oldCapacity >> 1))
    private Object[] grow(int minCapacity) {
        int oldCapacity = elementData.length;
        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth */
                    oldCapacity >> 1           /* preferred growth */);
            return elementData = Arrays.copyOf(elementData, newCapacity);
        } else {
        	// 无参构造方法实例化ArrayList,在这里初始化大小,容量为10
            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
        }
    }

    private Object[] grow() {
        return grow(size + 1);
    }

3. 总结

  • ArrayList默认初始化capacity为10,每次扩大1.5倍;
  • 如果知道数据量大小,建议使用带参数的构造方法进行初始化,可以减少被动扩容、数组复制等操作带来的性能消耗。
  • 注意区分同一package下Arrays的内部类$ArrayList, 二者有本质区别
package java.util;

public class Arrays {

    @SafeVarargs
    @SuppressWarnings("varargs")
    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

    /**
     * @serial include
     * Arrays$ArrayList内部类, 返回是数组,只提供get/set元素的方法,不能修改元素个数
     */
    private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private final E[] a;

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }
        ...
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值