加快链接列表?

时间:2010-11-27 22:01:12

标签: java optimization linked-list

我是一名学生,对Java很新。我正在查看Java,Linked List和ArrayList中两个集合实现的不同速度。我知道ArrayList在查找和将值放入索引时要快得多。我的问题是:

如果可能的话,如何更快地制作链表呢?

感谢您的帮助。

zmahir

9 个答案:

答案 0 :(得分:8)

在谈论速度时,也许你的意思是complexityArrayList(和数组)的插入和检索操作是O(1),而对于LinkedList,它们是O(n)。这不能改变 - 它是'按照定义'。

O(n)表示为了在给定位置插入对象或检索它,在最坏的情况下,必须遍历列表中的所有(n)项。因此n次操作。对于ArrayList,这只是一个操作。

答案 1 :(得分:2)

你可能不能。你不知道大小(嗯,你可以),也不知道每个元素的位置。要在链接列表中查找元素100,您需要从第1项开始,找到第2项的链接等,直到找到100.这使得在此列表中插入一项繁琐的工作。

根据您的具体目标,有很多选择。您可以使用b树或类似方法将大型链表拆分为较小的链表。如果您想快速查找项目,请使用哈希列表。或者使用简单的数组。但是如果你想要一个像ArrayList一样执行的列表,为什么不使用ArrayList?

答案 2 :(得分:2)

很多人比你更聪明,或者我已经看过Java集合类的实现。如果要进行优化,他们就会找到它并已经成功。

由于集合类几乎尽可能优化,我们的主要任务应该是选择正确的集合类。

选择收藏类型时,不要忘记HashSet之类的内容。如果顺序无关紧要,并且您不需要在集合中放置重复项,那么HashSet可能是合适的。

答案 3 :(得分:1)

使用跳过列表可以提高链接列表的速度:http://igoro.com/archive/skip-lists-are-fascinating/

答案 4 :(得分:0)

您可以拆分链接到主链接列表的区域,这样就可以直接在列表中为您提供入口点,这样您就不必走到它们前面。请在此处查看subList方法:http://download.oracle.com/javase/1.4.2/docs/api/java/util/AbstractList.html。如果您有多个由句子组成的“句子”,这很有用。您可以使用单独的链表来迭代句子,这些是主链表的子列表。

添加,删除或访问元素时,您还可以使用ListIterator。这有助于提高顺序访问的速度。请参阅listIterator方法和类:http://download.oracle.com/javase/1.4.2/docs/api/java/util/ListIterator.html

答案 5 :(得分:0)

链接列表使用指针来遍历项目,因此例如,如果您要求第5项,则运行时将从第一项开始并遍历每个指针,直到它到达第5项。

你真的没什么可做的。如果您需要快速访问项目,链接列表可能不是一个好的选择。虽然有一些优化,例如创建循环链表或双链表,您可以在列表中来回走动,但这实际上取决于业务逻辑和应用程序要求。

我的建议是,如果链接列表与您的需求不符,请避免使用链接列表,并且更改为不同的数据结构可能是最好的方法。

答案 6 :(得分:0)

作为一般规则,数据结构旨在很好地完成某些事情。 LinkedLists被设计为在插入元素和删除元素时比ArrayLists更快,并且在按顺序迭代列表时与ArrayLists相同。当您更改LinkedList的工作方式时,您不再使其成为真正的LinkedList,因此实际上没有任何方法可以将它们修改为更快的某些内容并且仍然是LinkedList。

您需要检查您使用此特定集合的方式,并确定LinkedList是否真的是最适合您的数据结构。如果您与我们分享您如何使用它,以及为什么您需要它更快,那么我们可以建议您应该考虑使用哪种数据结构。

答案 7 :(得分:0)

  

我是一名学生,对Java很新。 ...如果可能的话,如何更快地制作链表呢?

标准Java集合类型(实际上所有以任何语言实现的数据结构!)都代表了对各种“措施”的妥协,例如:

  • 表示数据结构所需的内存量。
  • 进行各种操作所需的时间;例如对于“列表”,感兴趣的操作是插入,删除,索引,包含,迭代等。
  • 集成/重用集合类型有多容易或多难;见下文。

例如:

  • ArrayList提供更低的内存开销,快速索引(O(1)),但缓慢包含,随机插入和删除(O(N))。
  • LinkedList具有更高的内存开销,索引速度慢且包含(O(N)),但在某些情况下删除速度更快(O(1))

各种性能指标通常由各种数据结构的数学决定。例如,如果您有一个节点链,获取ith节点的唯一方法是从头开始逐步执​​行它们。这涉及到i个指针。

有时您可以修改数据结构以改进性能的一个方面。但这通常是以性能的其他方面为代价的。 (例如,您可以添加单独的索引以更快地对链接列表进行索引。但是在插入/删除时维护索引的成本意味着您可能更好地使用ArrayList。)< / p>

在某些情况下,集成/重用要求会对性能产生重大影响。

例如,理论上可以通过向列表元素类型添加next字段来优化链表的空间使用,组合元素和节点对象并为每个列表条目保存16个左右的字节。但是,这会使列表类型不那么通用(成员/元素类需要实现特定的接口),并且具有元素在任何时候最多只能属于一个列表的限制。这些限制非常有限,因此Java中很少使用这种方法。

对于第二个例子,考虑在链表中的给定位置插入的问题。对于LinkedList类,这通常是O(N)操作,因为您必须单步执行列表才能找到该位置。理论上,如果应用程序可以找到并记住一个位置,它应该能够在O(1)中的那个位置执行插入。不幸的是,List API都没有提供“记住”职位的方法。

虽然这些示例都不是开发人员“做自己的事情”的根本障碍,但他们说明使用通用数据结构API和这些API的一般实现具有性能影响,因此代表了性能和性能之间的权衡。易用性的使用。

答案 8 :(得分:0)

我对这里的答案感到有些惊讶。 LinkedLists 和 ArrayLists 的理论性能与 Java 实现的实际性能相比存在很大差异。

Java LinkedList 比理论上的 LinkedList 慢的原因在于它所做的不仅仅是操作。例如,它检查并发修改和其他安全性。

如果你知道你的用例,你可以编写一个你自己的 LinkedList 的简单实现,它会更快。