ArrayList 扩容机制详解
ArrayList 扩容机制详解ArrayList 是 Java 用得最多的 List底层是动态数组。理解扩容机制能避免一些性能问题。1. 底层结构transientObject[]elementData;privateintsize;// 默认初始容量private static final int DEFAULT_CAPACITY 10;注意new ArrayList() 的时候elementData 是一个空数组不是长度 10 的数组。第一次 add 的时候才扩容到 10。 java private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA {}; public ArrayList() { this.elementData DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }2. add 操作publicbooleanadd(Ee){ensureCapacityInternal(size1);elementData[size]e;returntrue;}privatevoidensureCapacityInternal(intminCapacity){ensureExplicitCapacity(calculateCapacity(elementData,minCapacity));}privatestaticintcalculateCapacity(Object[]elementData,intminCapacity){if(elementDataDEFAULTCAPACITY_EMPTY_ELEMENTDATA)returnMath.max(DEFAULT_CAPACITY,minCapacity);// 第一次扩到 max(10, 1)returnminCapacity;}privatevoidensureExplicitCapacity(intminCapacity){modCount;if(minCapacity-elementData.length0)grow(minCapacity);// 需要扩容}3. grow 扩容privatevoidgrow(intminCapacity){intoldCapacityelementData.length;intnewCapacityoldCapacity(oldCapacity1);// 1.5 倍if(newCapacityminCapacity)newCapacityminCapacity;if(newCapacityMAX_ARRAY_SIZE)newCapacityhugeCapacity(minCapacity);elementDataArrays.copyOf(elementData,newCapacity);}扩容为原来的 1.5 倍oldCapacity oldCapacity / 2。Arrays.copyOf底层调用 System.arraycopy是 native 方法内存拷贝效率很高。4. 指定初始容量如果知道大概要放多少元素指定初始容量可以避免多次扩容// 知道要放 1000 个元素ListStringlistnewArrayList(1000);不指定的话10 → 15 → 22 → 33 → 49 → 73 → 109 → 163 → 244 → 366 → 549 → 823 → 1234。中间扩容了 12 次每次扩容都要数组拷贝频繁扩容会影响性能。特别是数据量大的时候一次扩容拷贝几万个元素耗时不少。5. 批量添加// addAll 效率更高ListStringlistnewArrayList(existingList.size());list.addAll(existingList);// 比 for 循环 add 好因为内部做了容量预检查6. trimToSizelist.trimToSize();// 缩小到实际 size大量删除后数组还有冗余空间可以用 trimToSize 回收内存。7. 数组和链表的选择ArrayList 随机访问 O(1)中间插入删除 O(n)。LinkedList 随机访问 O(n)头尾操作 O(1)。绝大多数场景 ArrayList 性能更好因为CPU 缓存对连续内存布局友好随机访问效率远高于链表的指针跳转。除非大量头尾操作否则优先用 ArrayList。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2637707.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!