Java / Scala 数组与链表对比
核心对比表
| 语言 / 类型 |
存储什么类型 |
底层结构 |
长度是否可变 |
随机访问 |
插入 / 删除 |
典型使用场景 |
Java int[] / long[] 等基本类型数组 |
直接存基本类型值 |
JVM 原生连续数组 |
固定 |
很快,O(1) |
慢,通常要移动或拷贝元素 |
长度已知、性能敏感、需要避免装箱 |
Java String[] / Object[] |
存对象引用 |
JVM 原生连续数组 |
固定 |
很快,O(1) |
慢,通常要移动或拷贝元素 |
固定长度对象集合、与底层 API 交互 |
Java ArrayList<T> |
存对象引用;基本类型会装箱为 Integer、Long 等 |
动态数组 |
可变 |
很快,O(1) |
尾部追加均摊 O(1);中间插入 / 删除 O(n) |
Java 最常用列表,适合读多、随机访问多、尾部追加多 |
Java LinkedList<T> |
存对象引用 |
双向链表 |
可变 |
慢,O(n) |
已定位节点后插入 / 删除快;查找位置仍是 O(n) |
头尾插入删除、双端队列场景;多数普通列表场景不推荐 |
Scala Array[T] |
Array[Int] 等可存 JVM 原始类型;对象数组存引用 |
JVM 原生连续数组 |
固定 |
很快,O(1) |
慢,通常要移动或拷贝元素 |
性能敏感、长度固定、Java 互操作 |
Scala ArrayBuffer[T] |
存泛型元素;基本类型通常涉及装箱 |
动态数组 |
可变 |
很快,O(1) |
尾部追加均摊 O(1);中间插入 / 删除 O(n) |
Scala 可变集合首选,适合追加和随机访问 |
Scala ListBuffer[T] |
存泛型元素;基本类型通常涉及装箱 |
可变链表,维护头尾指针 |
可变 |
慢,O(n) |
头部 / 尾部追加快,通常 O(1);中间操作仍需先查找 |
需要频繁头尾追加,并最终转成 List 的场景 |
Scala List[T] |
存泛型元素;基本类型通常涉及装箱 |
不可变单向链表 |
不可变 |
慢,O(n) |
头部追加 :: 很快,O(1);尾部追加慢 |
函数式递归、模式匹配、从头部构造集合 |
Scala Vector[T] |
存泛型元素 |
不可变树形数组结构 |
不可变 |
接近 O(1) |
追加、更新、访问都比较均衡 |
Scala 不可变序列的通用首选,很多场景比 List 更合适 |
操作复杂度对比
| 操作 |
数组 / 动态数组 |
链表 |
| 按下标访问 |
快,O(1) |
慢,O(n) |
| 顺序遍历 |
快,缓存友好 |
相对慢,节点分散、指针跳转多 |
| 尾部追加 |
动态数组均摊 O(1);原生数组不可变长 |
Java LinkedList 尾部追加 O(1);Scala List 尾部追加 O(n) |
| 头部追加 |
慢,通常要整体移动元素,O(n) |
快,尤其 Scala List 的 :: 是 O(1) |
| 中间插入 |
查找位置后还要移动元素,O(n) |
查找位置 O(n);已持有节点时插入快 |
| 中间删除 |
删除后要移动元素,O(n) |
查找位置 O(n);已持有节点时删除快 |
| 内存占用 |
较低,结构紧凑 |
较高,每个节点都有额外指针和对象开销 |
| CPU 缓存友好性 |
好 |
差 |
选型流程图
#mermaid-svg-NOVKiYHfnB2i98fc{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-NOVKiYHfnB2i98fc .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-NOVKiYHfnB2i98fc .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-NOVKiYHfnB2i98fc .error-icon{fill:#552222;}#mermaid-svg-NOVKiYHfnB2i98fc .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-NOVKiYHfnB2i98fc .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-NOVKiYHfnB2i98fc .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-NOVKiYHfnB2i98fc .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-NOVKiYHfnB2i98fc .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-NOVKiYHfnB2i98fc .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-NOVKiYHfnB2i98fc .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-NOVKiYHfnB2i98fc .marker{fill:#333333;stroke:#333333;}#mermaid-svg-NOVKiYHfnB2i98fc .marker.cross{stroke:#333333;}#mermaid-svg-NOVKiYHfnB2i98fc svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-NOVKiYHfnB2i98fc p{margin:0;}#mermaid-svg-NOVKiYHfnB2i98fc .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-NOVKiYHfnB2i98fc .cluster-label text{fill:#333;}#mermaid-svg-NOVKiYHfnB2i98fc .cluster-label span{color:#333;}#mermaid-svg-NOVKiYHfnB2i98fc .cluster-label span p{background-color:transparent;}#mermaid-svg-NOVKiYHfnB2i98fc .label text,#mermaid-svg-NOVKiYHfnB2i98fc span{fill:#333;color:#333;}#mermaid-svg-NOVKiYHfnB2i98fc .node rect,#mermaid-svg-NOVKiYHfnB2i98fc .node circle,#mermaid-svg-NOVKiYHfnB2i98fc .node ellipse,#mermaid-svg-NOVKiYHfnB2i98fc .node polygon,#mermaid-svg-NOVKiYHfnB2i98fc .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-NOVKiYHfnB2i98fc .rough-node .label text,#mermaid-svg-NOVKiYHfnB2i98fc .node .label text,#mermaid-svg-NOVKiYHfnB2i98fc .image-shape .label,#mermaid-svg-NOVKiYHfnB2i98fc .icon-shape .label{text-anchor:middle;}#mermaid-svg-NOVKiYHfnB2i98fc .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-NOVKiYHfnB2i98fc .rough-node .label,#mermaid-svg-NOVKiYHfnB2i98fc .node .label,#mermaid-svg-NOVKiYHfnB2i98fc .image-shape .label,#mermaid-svg-NOVKiYHfnB2i98fc .icon-shape .label{text-align:center;}#mermaid-svg-NOVKiYHfnB2i98fc .node.clickable{cursor:pointer;}#mermaid-svg-NOVKiYHfnB2i98fc .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-NOVKiYHfnB2i98fc .arrowheadPath{fill:#333333;}#mermaid-svg-NOVKiYHfnB2i98fc .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-NOVKiYHfnB2i98fc .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-NOVKiYHfnB2i98fc .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NOVKiYHfnB2i98fc .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-NOVKiYHfnB2i98fc .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NOVKiYHfnB2i98fc .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-NOVKiYHfnB2i98fc .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-NOVKiYHfnB2i98fc .cluster text{fill:#333;}#mermaid-svg-NOVKiYHfnB2i98fc .cluster span{color:#333;}#mermaid-svg-NOVKiYHfnB2i98fc div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-NOVKiYHfnB2i98fc .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-NOVKiYHfnB2i98fc rect.text{fill:none;stroke-width:0;}#mermaid-svg-NOVKiYHfnB2i98fc .icon-shape,#mermaid-svg-NOVKiYHfnB2i98fc .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NOVKiYHfnB2i98fc .icon-shape p,#mermaid-svg-NOVKiYHfnB2i98fc .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-NOVKiYHfnB2i98fc .icon-shape .label rect,#mermaid-svg-NOVKiYHfnB2i98fc .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NOVKiYHfnB2i98fc .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-NOVKiYHfnB2i98fc .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-NOVKiYHfnB2i98fc :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 固定
是
否
不固定
Java 可变
Scala 可变
是
否,主要头尾追加
Scala 不可变
是
否
是
否
需要一个有序集合
长度是否固定
是否性能敏感或存基本类型
Java/Scala Array
数组或普通 List 均可
是否需要可变集合
优先 ArrayList
是否需要频繁随机访问
优先 ArrayBuffer
ListBuffer
是否大量头部构造/递归匹配
Scala List
Scala Vector
是否主要当队列/双端队列用
优先 ArrayDeque
继续使用 ArrayList
简单结论
| 场景 |
推荐 |
| Java 普通列表 |
ArrayList |
| Java 固定长度、高性能、基本类型集合 |
原生数组,例如 int[] |
| Java 队列 / 双端队列 |
优先 ArrayDeque,通常不是 LinkedList |
| Scala 可变列表 |
ArrayBuffer |
Scala 可变、频繁头尾追加、最后要转 List |
ListBuffer |
| Scala 不可变通用序列 |
Vector |
| Scala 函数式递归、模式匹配、头部追加 |
List |
| 高频随机访问 |
数组、ArrayList、ArrayBuffer、Vector |
| 高频头部插入 |
Scala List 或合适的队列结构 |
| 高频中间插入删除 |
不要盲目选链表;JVM 链表对象开销大、缓存差,实际性能经常不如动态数组 |
一句话总结
数组适合固定长度和随机访问;动态数组是 Java / Scala 可变列表的主流选择;链表适合头部操作或已定位节点的插入删除;Scala ListBuffer 是可变链表,适合构造 List;Scala List 是不可变单向链表,不等同于 Java List;Scala 不可变序列多数情况下优先考虑 Vector。