为什么 ArrayList 总是比 LinkedList 快
Why is an ArrayList always faster than a LinkedList
昨天我 运行 在 Java 17 中进行了基准测试,我在其中重复创建了一个新的 Arraylist 和 Linkedlist 并向其中添加了 10.000.000 个元素。
根据 LinkedList 的性质,添加元素(创建 LinkedObject 并将其放在末尾)应该比添加到 ArrayList 快得多。 (将整个数组复制到另一个稍大的数组中。)
像 arraycopy() 这样的原生函数真的那么快吗? LinkedList 唯一擅长的是将两个 LinkedList 合并在一起。
大多数时候,添加到 ArrayList
不会 分配一个新数组,因为实现将后备数组的大小增加了 50%它需要成长。
从内存的角度来看这可能听起来很浪费,但即使是增长的最坏情况 ArrayList
使用的内存也少于 LinkedList
- 链表中的每个条目都需要一个对象头 + 3 个引用 (prev/value/next),而最坏情况下的增长 ArrayList
每个条目只有 1.5 个引用(即,使用的数组单元加上 50% 尚未使用的单元)。
任何人,根据我的计算,这意味着将 1000 万个条目添加到默认启动的 ArrayList
将导致大约 35 个数组复制操作,这不是很多。 (是的,System.arraycopy
很快。)
最后,如果您为数组提供 10_000_000
的初始容量,则创建的数组副本将为零。你可以试一下,看看复制到底要花多少钱。
昨天我 运行 在 Java 17 中进行了基准测试,我在其中重复创建了一个新的 Arraylist 和 Linkedlist 并向其中添加了 10.000.000 个元素。
根据 LinkedList 的性质,添加元素(创建 LinkedObject 并将其放在末尾)应该比添加到 ArrayList 快得多。 (将整个数组复制到另一个稍大的数组中。)
像 arraycopy() 这样的原生函数真的那么快吗? LinkedList 唯一擅长的是将两个 LinkedList 合并在一起。
大多数时候,添加到 ArrayList
不会 分配一个新数组,因为实现将后备数组的大小增加了 50%它需要成长。
从内存的角度来看这可能听起来很浪费,但即使是增长的最坏情况 ArrayList
使用的内存也少于 LinkedList
- 链表中的每个条目都需要一个对象头 + 3 个引用 (prev/value/next),而最坏情况下的增长 ArrayList
每个条目只有 1.5 个引用(即,使用的数组单元加上 50% 尚未使用的单元)。
任何人,根据我的计算,这意味着将 1000 万个条目添加到默认启动的 ArrayList
将导致大约 35 个数组复制操作,这不是很多。 (是的,System.arraycopy
很快。)
最后,如果您为数组提供 10_000_000
的初始容量,则创建的数组副本将为零。你可以试一下,看看复制到底要花多少钱。