繁体   English   中英

哪个列表<Object>实现最快,一次写入,读取,然后销毁?

[英]Which list<Object> implementation will be the fastest for one pass write, read, then destroy?

什么是最快的列表实现(在java中),在这种情况下,列表将一次创建一个元素,然后在以后的某个时刻读取一个元素? 读取将使用迭代器完成,然后列表将被销毁。
我知道get的Big O表示法是O(1),并且对于ArrayList,add是O(1),而LinkedList对于get是O(n),对于add是O(1)。 迭代器是否具有相同的Big O表示法?

这在很大程度上取决于您是否知道每个列表的最大大小。

如果这样做,请使用ArrayList ; 它肯定会更快。

否则,您可能需要进行个人资料。 虽然对ArrayList访问是O(1),但由于动态调整大小,创建它并不是那么简单。

需要考虑的另一点是,时空权衡并不明确。 每个Java对象都有相当多的开销。 虽然ArrayList可能会在剩余插槽上浪费一些空间,但每个插槽只有4个字节(或64位JVM上为8个字节)。 LinkedList每个元素可能大约为50个字节(在64位JVM中可能为100个字节)。 因此,在LinkedList实际赢得其假定的空间优势之前,您必须在ArrayList拥有相当多的浪费的插槽。 引用的位置也是一个因素,并且ArrayList也是优选的。

在实践中,我几乎总是使用ArrayList

第一个想法:

  • 重构您的代码以不需要列表。
  • 将数据简化为标量数据类型,然后使用: int []
  • 或者甚至只使用你拥有的任何对象的数组: Object [] - John Gardner
  • 将列表初始化为完整大小: new ArrayList(123);

当然,正如其他人提到的那样,进行性能测试,证明您的新解决方案是一种改进。

迭代链表是每个元素O(1)。

每个选项的Big O运行时都是相同的。 由于更好的内存局部性,ArrayList可能会更快,但你必须测量它才能确定。 挑选任何使代码最清晰的东西。

注意,如果天真地进行迭代,则迭代通过LinkedList的实例可以是O(n ^ 2)。 特别:

List<Object> list = new LinkedList<Object>();
for (int i = 0; i < list.size(); i++) {
    list.get(i);
}

这是在效率方面绝对可怕由于该列表必须经过多达i每次迭代的两倍 如果您确实使用LinkedList ,请确保使用Iterator或Java 5的增强型for -loop:

for (Object o : list) {
    // ...
}

上面的代码是O(n),因为列表是在原地遍历的。

要避免上述所有麻烦,只需使用ArrayList 它并不总是最佳选择(特别是对于空间效率),但它通常是一个安全的选择。

我建议对它进行基准测试。 阅读API是一回事,但在你自己尝试之前,它是学术性的。

应该公平易于测试,只要确保你做有意义的操作,或者热点会超出你的智能并优化它到NO-OP :)

你几乎肯定想要一个ArrayList 添加和读取都是“摊销的常量时间”(即O(1)),如文档中所指定的(请注意,即使列表必须增加它的大小,这也是正确的 - 它的设计类似于http://java.sun .com / j2se / 1.5.0 / docs / api / java / util / ArrayList.html )。 如果您大致知道要存储的对象数量,那么甚至可以消除ArrayList大小的增加。

添加到链接列表的末尾是O(1),但常量乘数​​大于ArrayList(因为您通常每次都创建一个节点对象)。 如果使用迭代器,则读取与ArrayList几乎完全相同。

除非有充分的理由不这样做,否则总是使用最简单的结构是一个很好的规则。 这里没有这样的理由。

ArrayList文档的确切引用是:“添加操作以分摊的常量时间运行,即添加n个元素需要O(n)时间。所有其他操作都以线性时间运行(粗略地说)。常量因子与LinkedList实现相比较低。“

有一个名为GlueList的新List实现,它比所有经典的List实现更快。

我实际上已经开始认为应该避免使用具有非确定性行为的数据结构,例如ArrayList或HashMap,所以我想说如果你可以绑定它的大小,只使用ArrayList; 任何无界列表都使用LinkedList。 那是因为我主要编写具有接近实时要求的系统。

主要问题是任何内存分配(可能随任何添加操作随机发生)也可能导致垃圾收集,任何垃圾收集都可能导致您错过目标。 分配越大,发生的可能性越大,如果使用CMS收集器,这也会更加复杂。 CMS是非压缩的,因此为新的链表节点寻找空间通常比为新的10,000个元素阵列寻找空间更容易。

您的编码方法越严格,您就可以越接近实时库存JVM。 但是,仅选择具有确定性行为的数据结构是您必须采取的第一步。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM