【Java集合专项】-ArrayList和LinkedList源码分析(2)

一、ArrayList源码分析

(一)ArrayList初始化的时候容量为0

(1)初始化ArrayList

        //创建集合
        ArrayList arrayList = new ArrayList();

上面的代码是进行ArrayList的初始化,然后我们进入到ArrayList的构造方法中。

(2)无参数的构造方法

    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

然后我们到

DEFAULTCAPACITY_EMPTY_ELEMENTDATA 这个数组。
    /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

可以看出 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 是定义了一个空数组。

所以,当我们初始化ArrayList的时候,ArrayList的初始化容量为空数组。

(二)ArrayList的Add方法

    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

(1)我们点击 ensureCapacityInternal 方法,elementData存放元素的数组 ,size实际元素的个数,size为0。

    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }
    /**
     * Default initial capacity.
     */
    private static final int DEFAULT_CAPACITY = 10;

因为 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 为空数组,当开始的时候,elementData 等于DEFAULTCAPACITY_EMPTY_ELEMENTDATA,这个条件成立,所以走到了,if里面,然后

DEFAULT_CAPACITY 和 minCapacity 进行对比,谁最大赋值给 minCapacity ,因为我们要添加第一个元素,所以一定是 DEFAULT_CAPACITY 这个最大,所以当我们添加第一个元素的时候,集合的容量变成了10.

当if条件走完之后,我们来到了        ensureExplicitCapacity(minCapacity); 

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

现在minCapacity为10,所以if条件是成立的,
 

    /**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     *
     * @param minCapacity the desired minimum capacity
     */
    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);
    }
elementData刚开始是没有的,所以 oldCapacity为0,int newCapacity = oldCapacity + (oldCapacity >> 1); 此时newCapacity为 0,0-10成立,所以newCaoacity= 10,所以elementData为10.

注意:oldCapacity >> 1 的意思是右移動1位,还是0.相当于除2  

扩容:

        int newCapacity = oldCapacity + (oldCapacity >> 1);

如果没有向集合中添加任何元素时,容量0,添加一个元素之后,容量10,每次扩容大小为原来的1.5倍。

二、LinkedList源码分析

(1)存储结构

LinkedList的存储结构为双向链表,size为大小,first指向第一个元素,last指向最后一个元素。

    transient int size = 0;

    /**
     * Pointer to first node.
     * Invariant: (first == null && last == null) ||
     *            (first.prev == null && first.item != null)
     */
    transient Node<E> first;

    /**
     * Pointer to last node.
     * Invariant: (first == null && last == null) ||
     *            (last.next == null && last.item != null)
     */
    transient Node<E> last;

    /**
     * Constructs an empty list.
     */
    public LinkedList() {
    }

(2)add方法

    /**
     * Appends the specified element to the end of this list.
     *
     * <p>This method is equivalent to {@link #addLast}.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        linkLast(e);
        return true;
    }
    /**
     * Links e as last element.
     */
    void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }

此时,我们点击Node。 

    private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

当添加第一个元素的时候,元素的类型为Node,fast指向就不为空了,是一个结点,这个结点是item是实际数据,next为下一个结点,prev为前一个结点。

    /**
     * Links e as last element.
     */
    void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }

我们再看linkLast,l是Prev,null为last

执行

      final Node<E> newNode = new Node<>(l, e, null);

当执行last = newNode; 这句代码

当执行到       if (l == null) ,  first = newNode;

当添加第二个元素执行的时候,         final Node<E> newNode = new Node<>(l, e, null);

此时last还是指向e1的,当我们执行到last=newcode,就变成了last指向e2了, 

 当我们再执行l.next=newNode的时候

其他文章:

【Java集合专项】-List(ArrayList和LinkedList)基础(1)

猜你喜欢

转载自blog.csdn.net/MyxZxd/article/details/110342565