arraylist头部插入时间复杂度为o(n),因每次调用add(0, item)均触发system.arraycopy复制全部元素;而尾部插入均摊o(1),linkedlist和arraydeque头插则严格或均摊o(1)。

因为 ArrayList 底层是连续数组,每次在头部(索引 0)插入元素,都要把原有所有元素向后平移一位,时间复杂度是 O(n)。
底层操作实际发生了什么
调用 list.add(0, item) 时,ArrayList 内部会执行 System.arraycopy,把从索引 0 开始的全部元素复制到新位置。例如:10 万个字符串的列表,插入一个新元素到开头,就要移动 10 万次引用——不是“慢一点”,而是“量级级拖慢”。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
和尾部插入对比鲜明
- 尾部插入(add(item)):通常只需写入下一个空位,均摊 O(1),扩容时才触发复制
- 头部插入:每次必复制全部后续元素,没有摊还优化,纯 O(n)
为什么 LinkedList 或 ArrayDeque 就快得多
LinkedList 是双向链表,头插只需新建节点、调整头结点的前后指针,不移动其他数据,严格 O(1)。
ArrayDeque 是循环数组,头插通过递减头索引实现,同样均摊 O(1),且内存更紧凑、CPU 缓存友好,实际性能通常优于 LinkedList。
临时缓解但不治本的方法
- 用 addAll(0, collection) 替代多次 add(0, item) —— 减少方法调用开销,但依然要移动全部原元素
- 先收集待插元素到另一个集合,再一次性插入 —— 合并操作,降低 JVM 调用频次
- 把“头部插入”逻辑反转为“尾部插入”,最后调用 Collections.reverse(list) —— 仅适用于最终需全量处理且顺序可延后确定的场景
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










