zoukankan      html  css  js  c++  java
  • java ArrayList源码分析(转载)

    1.ArrayList是一个相对来说比较简单的数据结构,最重要的一点就是它的自动扩容,可以认为就是我们常说的“动态数组”。
      来看一段简单的代码:

    1
    2
    3
    4
    5
    ArrayList<String> list = new ArrayList<String>();
    list.add("语文: 99");
    list.add("数学: 98");
    list.add("英语: 100");
    list.remove(0);

    在执行这四条语句时,是这么变化的:
    arraylist
    其中,add操作可以理解为直接将数组的内容置位,remove操作可以理解为删除index为0的节点,并将后面元素移到0处。

    2. add函数

    当我们在ArrayList中增加元素的时候,会使用add函数。他会将元素放到末尾。具体实现如下:

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

    我们可以看到他的实现其实最核心的内容就是ensureCapacityInternal。这个函数其实就是自动扩容机制的核心。我们依次来看一下他的具体实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    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);
    }

    private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    // 扩展为原来的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 如果扩为1.5倍还不满足需求,直接扩为需求值
    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);
    }

    也就是说,当增加数据的时候,如果ArrayList的大小已经不满足需求时,那么就将数组变为原长度的1.5倍,之后的操作就是把老的数组拷到新的数组里面。例如,默认的数组大小是10,也就是说当我们add10个元素之后,再进行一次add时,就会发生自动扩容,数组长度由10变为了15具体情况如下所示:
    arraylistadd

    3 set和get函数

    Array的put和get函数就比较简单了,先做index检查,然后执行赋值或访问操作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public E set(int index, E element) {
    rangeCheck(index);

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

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

    return elementData(index);
    }

    4 remove函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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);
    // 把最后的置null
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
    }

    注释很清楚:

    Removes the element at the specified position in this list. Shifts any subsequent elements to the left (subtracts one from their indices).

  • 相关阅读:
    10.28
    10.25
    10.21
    移动第七次作业
    移动第六次作业
    移动第五次作业
    移动第四次作业
    移动第3次作业
    移动第二次作业
    移动第一次作业
  • 原文地址:https://www.cnblogs.com/mr-wuxiansheng/p/6504818.html
Copyright © 2011-2022 走看看