ArrayList默认容量为10是OpenJDK权衡内存与扩容开销的设定;扩容按1.5倍增长,频繁add小量元素会触发多次复制,预设容量可避免;扩容非线程安全;LinkedList随机访问O(n)远慢于ArrayList的O(1),仅首尾操作占优。

ArrayList 为什么默认容量是 10?扩容机制怎么影响性能?
Java 中 ArrayList 初始化时不指定容量,底层 Object[] 数组默认长度为 10。这不是硬编码魔法值,而是 OpenJDK 源码里写死的 DEFAULT_CAPACITY = 10,权衡了内存占用与首次扩容开销。
扩容发生在 add() 时发现数组已满:新容量 = 旧容量 × 1.5(即 oldCapacity + (oldCapacity >> 1)),然后调用 Arrays.copyOf() 复制整个数组。这意味着:
- 频繁 add 小量元素(如循环中逐个添加 20 个)会触发 2 次扩容(10 → 15 → 22),产生冗余复制
- 若提前知道大小(比如从数据库查出 1000 条记录),直接 new
ArrayList(1000)可避免所有扩容 - 扩容不是线程安全的,多线程同时 add 可能导致数组复制不完整或
ArrayIndexOutOfBoundsException
LinkedList 真的适合随机访问吗?哪些操作反而比 ArrayList 慢?
LinkedList 是双向链表实现,get(int index) 必须从头或尾遍历节点,时间复杂度 O(n),而 ArrayList 是数组,get() 是 O(1)。实测在 10 万元素下,LinkedList.get(50000) 比 ArrayList.get(50000) 慢 30 倍以上。
真正适合 LinkedList 的场景只有:addFirst()、addLast()、removeFirst()、removeLast() 这四类操作(O(1))。其他情况要注意:
立即学习“Java免费学习笔记(深入)”;
-
add(int index, E element)需先遍历到位置,再插入节点 —— 比ArrayList的同名方法更慢 - 每个元素额外占用两个引用字段(prev/next),内存开销比
ArrayList高约 40% - JVM 无法对链表做连续内存预取,CPU 缓存命中率低,实际吞吐常低于理论
Vector 和 ArrayList 的线程安全差异在哪?为什么现在基本不用 Vector?
Vector 的方法(如 add()、get())全部加了 synchronized,锁的是整个对象实例。这导致:
- 即使只读操作(
get())也要竞争同一把锁,吞吐量远低于无锁的ArrayList - 复合操作(如“检查是否存在再添加”)仍需外部同步,
Vector的单个方法同步无法保证原子性 - 自 JDK 1.5 起,推荐用
Collections.synchronizedList(new ArrayList())或更优的CopyOnWriteArrayList(适用于读多写少)
现代代码几乎见不到 Vector,除非维护 20 年前的遗留系统。
subList() 返回的是新 List 吗?修改它会影响原列表吗?
subList(int fromIndex, int toIndex) 不创建新集合,而是返回一个内部 SubList 视图,底层仍指向原 ArrayList 的同一数组。这意味着:
- 对
subList调用set()、remove()、add(),会直接修改原列表内容 - 原列表结构变更(如
clear()或扩容)会导致subList抛ConcurrentModificationException - 若需要独立副本,必须显式构造:
new ArrayList(list.subList(0, 5))
这个“视图非副本”的特性极易被忽略,尤其在多线程或嵌套调用中传参时,容易引发隐蔽的数据污染。










