JavaのArrayListには、詳細な

これまでのところ唯一の懸念を記録します。JDK1.8

まず、基本的なプロパティ

1.1内部パラメータ

    //空存储实例。直接new ArrayList()便是以该空数组作为实例
    private static final Object[] EMPTY_ELEMENTDATA = {};

    //默认容量大小,在由空实例进行首次扩容时,扩到到该长度。
    //实际使用中,并未实际存在Capacity这个参数,需要扩容时直接根据旧数组的length进行扩容
    private static final int DEFAULT_CAPACITY = 10;

    //实际存储数组
    transient Object[] elementData;

    //存储元素个数
    private int size;

三つのコンストラクタのオーバーロード1.2

    //构建一个空实例,elementData指向容量为0的空数组
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    //以给定容量初始化存储数组
    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);
        }
    }

    //以集合初始化创建列表
    //步骤:1. 调用toArray(),将给定集合转成数组(以ArrayList为例,toArray()返回的是实际存在元素的那部分数组,即[0,size))
    //2. 让size直接等于给定集合的数组长度
    //3. 判断size如果为0则直接创建空存储实例,否则使用Arrays.copyOf将给定集合数组复制一份(浅拷贝),作为存储数组
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

    // ArrayList 的 toArray()源码,复制[0,size)部分返回
    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

第二に、操作と戦略

2.1動的な拡張

拡大戦略:拡張する前に、すべてのフルの配列、新しい長さ=長さ+古い古い長さ* 2

動的拡張は、二つの入り口があります明示的なユーザー・コールの拡張をensureCapacity()暗黙の要素の間の拡張を追加しensureCapacityInternal()たが、呼び出されるensureExplicitCapacity()実際の膨張に着信膨張、最終操作に基づいて、必要な容量値かどうかを決定するgrow()プロセス。

    //显式扩容入口方法
    public void ensureCapacity(int minCapacity) {
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            // any size if not default element table
            ? 0
            // larger than default for default empty table. It's already
            // supposed to be at default size.
            : DEFAULT_CAPACITY;

        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
    }

    //隐式扩容入口方法
    //其中参数 minCapacity 值为 size+1,由add方法调用传入
    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    //添加方法
    public boolean add(E e) {
        // 传入最小所需容量为size+1
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }


    //计算所需容量,实则不需要计算
    //只是单纯判断当前是否是空实例,为空就话返回 "默认容量"与minCapacity之间的较大值,不为空直接返回minCapacity
    //参数 minCapacity 只有两种情况:
    // 1. 隐式扩容时,如add()传入,其值为 size+1
    // 2. 显式扩容,用户指定
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }
    
    //在此处,根据最小所需容量来判断是否实际进行扩容
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0) //若已经占满,才进行扩容
            grow(minCapacity);
    }

    //实际扩容方法
    //可以看到扩容策略为:length+length*2
    //然后调用Arrays.copyOf浅复制
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1); //旧长度+旧长度*2
        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);
    }

おすすめ

転載: www.cnblogs.com/simpleito/p/10926385.html