美文网首页
ArrayList源码解析

ArrayList源码解析

作者: IT_lz | 来源:发表于2019-05-31 16:21 被阅读0次

    1、构造方法初始化

    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);
        }
    }
    
    • ArrayList底层由数组构成,如果用户未指定数组大小,则赋值为默认的数组EMPTY_ELEMENTDATA(这是一个空数组,在添加第一个元素时,会扩容为DEFAULT_CAPACITY = 10 大小的数组)。
    • 用户指定大小后,将按照指定大小创建数组。

    2、Add方法

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    
    • List接口下的集合是可以允许加入重复的元素,所以add方法永远返回true。

    • ensureCapacityInternal(int x)检测加入元素之后的大小是否超出目前的长度, 如果超过则扩容。

      扩容机制 :

      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);
      }
      
    扩容流程.png
    • Arrays.copyOf(elementData, newCapacity);

    ​ 第二个变量为新数组的长度,如果新数组长度超过老数组长度,则多出来的元素为默认值。

    • 最后向扩容后的数组中添加元素。到此添加工作已完成。

    3、remove()移除元素

    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);
        elementData[--size] = null; // clear to let GC do its work
    
        return oldValue;
    }
    
    1. 获取当前要返回的值,用于返回。
    2. 将移除的目标元素后面的元素向前平移对齐。
    3. 将最后一个元素置null。在GC时回收掉。
    • System.arraycopy与Arrays.copyOf区别
      1. System.arraycopy操作已有数组。
      2. Arrays.copyOf拷贝之后会生成新的数组。

    4、get()获取某个位置的值

    public E get(int index) {
        rangeCheck(index);
    
        return elementData(index);
    }
    
    1. 检查index是否越界,越界则报"IndexOutOfBoundsException"。
    2. 返回数据结果。

    相关文章

      网友评论

          本文标题:ArrayList源码解析

          本文链接:https://www.haomeiwen.com/subject/xdrgtctx.html