超详细的ArrayList扩容过程(配合源码详解)

打印 上一主题 下一主题

主题 881|帖子 881|积分 2643

首先,在调用add方法的时候 ,会去调用 ensureCapacityInternal  方法,传入一个参数 minCapacity 大小是size + 1,也就是现在我们需要的数组的最小的大小。
在ensureCapacityInternal 方法中,先判定一下elementdata是不是初始空数组
是的话就把minCapacity变动为默认容量 也就是10, 和传进来的minCapacity的最大值
之后调用 ensureExplicitCapacity  方法,把现在的minCapacity传进去
  1. private void ensureCapacityInternal(int minCapacity) {
  2.     if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
  3.         minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
  4.     }
  5.     ensureExplicitCapacity(minCapacity);
  6. }
复制代码
第二步:
在这个ensureExplicitCapacity 方法中,会去判定一下传进来的minCapacity和当前elementdata的大小,如果需要的这个最小容量已经超过了当前数组的长度,就会去调用grow方法,也就是扩容的核心方法,并且把这个minCapacity传进去
  1. private void ensureExplicitCapacity(int minCapacity) {
  2.     modCount++;
  3.     if (minCapacity - elementData.length > 0)
  4.         grow(minCapacity);
  5. }
复制代码
第三步:
进入grow方法后,先去获取现在的elementdata的长度,并且先行扩容到1.5倍(这个>>1是位运算)。扩容后的容量记为 newCapacity  ,用这个newCapacity 去和minCapacity也就是我们需要的最小的大小进行比较,还是达不到的话就让newCapacity=minCapacity。接着还要处理一下当前的newCapacity超过MAX_ARRAY_SIZE,也就是ArrayList允许的数组最大值的环境(一般是Integer.MAX_VALUE - 8)。调用hugeCapacity来进行处理,小于0的话就抛异常,超过最大值了就取最大值。最后调用Arrays.copyOf()方法。
  1. private void grow(int minCapacity) {
  2.     int oldCapacity = elementData.length;
  3.     int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容到原来的 1.5 倍
  4.     if (newCapacity - minCapacity < 0)
  5.         newCapacity = minCapacity; // 若新容量仍不足,则取所需的最小容量
  6.     if (newCapacity - MAX_ARRAY_SIZE > 0)
  7.         newCapacity = hugeCapacity(minCapacity); // 检查是否超过最大允许大小
  8.     elementData = Arrays.copyOf(elementData, newCapacity);
  9. }
复制代码
  1. private static int hugeCapacity(int minCapacity) {
  2.     if (minCapacity < 0) // overflow
  3.         throw new OutOfMemoryError(); // 超出 int 最大值时抛出异常
  4.     return (minCapacity > MAX_ARRAY_SIZE) ?
  5.            Integer.MAX_VALUE : // 如果实际需求超大,则直接取 Integer.MAX_VALUE
  6.            MAX_ARRAY_SIZE;     // 否则取最大允许的数组大小
  7. }
复制代码
最后在这个Arrays.copyOf()方法中会创建一个新的数组,大小就是我们上一步得到并且传入的newCapacity。接着把旧数组中的元素拷贝到新数组中。
  1. public static <T> T[] copyOf(T[] original, int newLength) {
  2.     T[] copy = (T[]) Array.newInstance(original.getClass().getComponentType(), newLength);
  3.     System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
  4.     return copy;
  5. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

愛在花開的季節

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表