arraylist的get(index)为o(1),因数组连续内存可直接计算地址;add(e e)末尾添加平均o(1),但扩容时o(n);add(int index, e e)固定o(n),因需移动元素。

add 和 get 的时间复杂度差异,核心在于 ArrayList 底层是数组 —— 连续内存、支持下标直访,但插入不一定只在末尾。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
get(index) 是 O(1),因为直接算地址
数组中每个元素大小相同、地址连续,给定 index,JVM 可直接计算出内存偏移量:
baseAddress + index × elementSize
无需遍历,也不依赖元素数量 n,所以是严格常数时间。
add(E e) 通常 O(1),但扩容时退化为 O(n)
默认在末尾添加,只要容量够,就直接写入 elementData[size++],不移动其他元素 —— 这是 O(1)。
但当 size == elementData.length 时,必须扩容:
- 创建新数组(通常是原容量 1.5 倍)
- 调用 System.arraycopy() 把全部旧元素复制过去
- 这一步要拷贝 n 个引用,耗时正比于当前元素个数 → O(n)
add(int index, E e) 固定是 O(n)
无论是否扩容,只要插在中间或开头,就必须为新元素腾位置:
- 从 index 开始,把 elementData[index] ~ elementData[size-1] 全部向后复制一位
- 移动的元素个数平均为 n/2,最坏(插在开头)是 n 个 → 统一看作 O(n)
摊还分析让 add(E e) 仍可称“平均 O(1)”
虽然单次扩容代价高,但扩容不频繁:容量按 1.5 倍增长,意味着每 O(n) 次 add 才触发一次 O(n) 扩容。
总代价分摊到所有操作上,平均每次仍是常数级。面试中提到“摊还复杂度”就是这个意思。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










