ArrayList的扩容方式和扩容时机?
面试题
1 个回答
自己喜欢的东西,就不要问别人好不好。粑粑### ArrayList 的扩容方式和扩容时机 ArrayList 底层是一个动态数组,ArrayList 首先会对传入的初始化参数 `initialCapacity` 进行判断: 1. 如果参数等于 0,则将数组初始化为一个空数组。 2. 如果参数不等于 0,则将数组初始化为一个容量为 10 的数组(或者自定义指定的容量)。 随着不断添加元素,数组大小增加,当数组的大小大于初始容量时(例如,初始容量为 10,当添加第 11 个元素时),就会进行扩容,新的容量为旧的容量的 1.5 倍。 扩容时,会以新的容量创建一个原数组的拷贝,修改原数组指向这个新数组,原数组会被抛弃并被 GC 回收。 #### ArrayList 的扩容源码解析 ```java // ArrayList 初始化容量判断 public void ensureCapacity(int minCapacity) { int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) ? 0 : DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } } // 添加元素的方法 public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } // 判断是否需要扩容 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; 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); } ``` #### 关键点总结 1. **初始化容量判断**: - 如果传入的 `initialCapacity` 为 0,则初始化为一个空数组。 - 如果 `initialCapacity` 不为 0,则初始化为一个容量为 10 的数组,或指定的容量。 2. **添加元素时判断是否需要扩容**: - 在添加元素前调用 `ensureCapacityInternal(size + 1)` 进行容量检查。 - 如果需要扩容,则调用 `ensureExplicitCapacity(minCapacity)`。 3. **扩容机制**: - 获取旧的容量 `oldCapacity`。 - 新的容量 `newCapacity` 为旧容量的 1.5 倍。 - 如果新容量仍小于最小所需容量 `minCapacity`,则将新容量设为 `minCapacity`。 - 如果新容量超过最大数组大小 `MAX_ARRAY_SIZE`,则调用 `hugeCapacity(minCapacity)` 进行处理。 - 通过 `Arrays.copyOf` 将旧数组内容复制到新数组中。 这种扩容机制保证了 ArrayList 在需要时能够动态增加容量,同时尽量减少扩容次数,以提高性能。编辑于 2024-02-19 11:48 •IP属地 北京举报评论收藏1
公众号进入网站体验更佳

