MST

星途 面试题库

面试题:Java集合框架之ArrayList源码相关

请简述Java中ArrayList的扩容机制,从源码层面分析其在扩容时的具体操作步骤及涉及到的关键方法。
42.4万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

ArrayList扩容机制源码分析

  1. 关键属性
    • elementData:是一个Object类型的数组,用于存储ArrayList中的元素。
    • size:记录ArrayList中实际元素的数量。
    • DEFAULT_CAPACITY:默认初始容量,值为10。
  2. 扩容触发时机
    • 当向ArrayList中添加元素时,如果size达到了elementData数组的容量(即size == elementData.length),就会触发扩容。例如,调用add(E e)方法时:
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    
  3. 具体操作步骤及关键方法
    • ensureCapacityInternal方法
      • 首先调用calculateCapacity方法来确定所需的最小容量。
      private static int calculateCapacity(Object[] elementData, int minCapacity) {
          if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
              return Math.max(DEFAULT_CAPACITY, minCapacity);
          }
          return minCapacity;
      }
      
      • 然后调用ensureExplicitCapacity方法,该方法会检查所需的最小容量是否大于当前数组的容量,如果是,则调用grow方法进行扩容。
      private void ensureExplicitCapacity(int minCapacity) {
          modCount++;
      
          // overflow-conscious code
          if (minCapacity - elementData.length > 0)
              grow(minCapacity);
      }
      
    • grow方法
      • 计算新的容量,新容量为旧容量的1.5倍(int newCapacity = oldCapacity + (oldCapacity >> 1);oldCapacity >> 1相当于oldCapacity / 2)。
      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);
      }
      
      • 如果新容量仍然小于所需的最小容量minCapacity,则将新容量设置为minCapacity
      • 如果新容量超过了MAX_ARRAY_SIZEInteger.MAX_VALUE - 8),则调用hugeCapacity方法来处理。hugeCapacity方法会根据minCapacity是否大于MAX_ARRAY_SIZE,返回Integer.MAX_VALUE或者MAX_ARRAY_SIZE
      • 最后通过Arrays.copyOf方法将旧数组的内容复制到新的、容量更大的数组中,完成扩容。

综上所述,Java中ArrayList的扩容机制通过一系列方法协同工作,在元素数量达到数组容量时,以1.5倍的方式增加容量,并复制旧数组内容到新数组,以保证ArrayList能继续存储更多元素。