【问题标题】:What is the purpose of a LinkedList in Java Considering an ArrayList Has No Size Limit?考虑到 ArrayList 没有大小限制,Java 中 LinkedList 的目的是什么?
【发布时间】:2021-10-12 19:14:08
【问题描述】:

在许多帖子中,当我阅读到 LinkedList 的好处时,我听到的最常见的好处是,在某些情况下,LinkedList 的性能更高,因为插入和删除比在数组中更快。

具体来说,参数是数组使用效率较低,因为为了扩展它们,需要将内容复制到具有更大声明大小的不同数组。

但是,由于 Java 有 ArrayList,它没有容量限制,所以关于 LinkedLists 性能更高的这一点似乎是无效的。链接列表现在在 Java 中已经过时了吗?有没有什么情况下 LinkedList 实际上仍然比 Java 中的 ArrayList 更好?

【问题讨论】:

  • "没有容量限制" - ArrayList 仍然由数组支持,但它只是为您隐藏了数组扩展和复制。
  • 有没有想过为什么 ArrayList被称为“array list”?它在底层使用了一个数组。
  • 你是对的,你不太可能需要LinkedList。作为一名 Java 程序员,我在 20 多年的时间里使用过一次,现在回想起来就后悔了。
  • 在 Java 之前似乎有使用链表的传统,所以我猜他们认为最好在 Java 集合框架中也包含一个。因此,如果我是对的,其目的是展示人们将认为是一整套集合实现的内容。这是一种避免因缺点而受到批评的简单方法,无论这种批评是否有效。目的并不实际。
  • 最糟糕的是他们在面试候选人时仍然被用于技术面试

标签: java arrays algorithm linked-list big-o


【解决方案1】:

假设您有一个包含 100,000 个(或类似的大数量)元素的列表。

假设您想在开头或中间的某个位置插入一个元素。

使用 ArrayList,您需要将每个元素向后移动一个位置以腾出空间。这显然需要O(n) 操作。

使用 LinkedList,您只需创建一个新节点并将其插入。如果您已经知道需要它的位置,这就是 O(1) 操作。

对于删除反之亦然 - 特别是随着列表大小变大,并且随着索引相对于插入和删除变得不那么重要,链表比数组列表具有性能优势。

从教育的角度来看,链表展示的概念对于以后扩展到树和图表很重要。但这不是你要问的。

【讨论】:

  • 非常感谢您花时间解释这一点。您的回答确实为我阐明了这一点。
  • 要在开头插入,您显然需要使用ArrayDeque,而不是LinkedList。即使在某些情况下插入一个大列表的中间,使用ArrayList 测量的整体性能也更好,因为以这种方式使用的LinkedList 往往会分布在更多的内存页面上,因此会导致抖动。
【解决方案2】:

考虑到 ArrayList 没有大小限制,Java 中 LinkedList 的目的是什么?

LinkedList 在客观上优于ArrayList 的情况并不多。

首先是一些基本事实:

  • 两种列表类型的大小都是动态的(没有区别)。
  • ArrayList 每个元素占用的内存少于LinkedList。 4 倍或更多。 (每个元素一个指针,而不是三个指针加上堆节点的开销。)
  • 如果您严重错误地估计了ArrayList 的初始容量,它可以使用比LinkedList 更多的内存。 (但这确实是一个应用程序错误。)
  • ArrayList 的大多数操作都更快。
    • 位置操作是O(1)O(N)
    • 局部性与内存缓存/TLB 缓存/VM 页面未命中的性能影响对于大型列表可能非常重要。
  • LinkedList 的某些操作可能更快;例如插入和删除。但是,这取决于具体情况;例如插入或删除的位置,或者操作是否触发后备数组的扩展。

那么LinkedList 可能有优势的情况是什么?

一种情况是在列表的开头添加和删除元素。这是O(1) 用于LinkedListO(N) 用于ArrayList。 (ArrayDeque 通常是比LinkedList 更好的替代方案...除了它没有实现List API。)

第二种情况是遍历列表并在遍历期间添加或删除元素。 LinkedList.listIterator 方法返回一个ListIterator,允许您在当前位置添加或删除元素。这些是O(1) 操作。

第三,如果您的应用程序极度不能容忍(例如)可能需要很长时间的列表追加,LinkedList 可能会更有利。 (想想硬实时应用程序......)

最后,说ArrayList 没有大小限制实际上是不正确的。它实际上仅限于略低于 2^31 个元素。这是因为 Java 数组被 JVM 限制为略低于 2^31 个元素。 LinkedList没有这个问题。


现在 Java 中的 LinkedLists 已经过时了吗?

没有。

这个类很少使用(而且一直都是),但它并没有过时。

我记得 Brian Goetz 曾说过,回想起来,实施LinkedList 可能不值得。但考虑到付出的努力,您应该在需要时随意使用该类。


请注意,您需要考虑对列表执行的所有操作。这通常很难提前完成。而且(程序员)的努力通常是不合理的。由于ArrayList 通常被证明是最佳选择,因此它是大多数程序员的默认选择。

避免过早优化的陷阱......

【讨论】:

  • 一种情况是在列表的开头添加和删除元素。 不要为此使用LinkedList。使用ArayDeque。我的意思是,很明显。
  • 感谢您的回答。
  • 嗯...是的...但是ArrayDeque 不允许您执行其他列表操作。
【解决方案3】:

ArrayList 里面有一个数组,为了动态它有时需要扩展内部数组。 Internal Working of ArrayList in Java

【讨论】:

    【解决方案4】:

    ArrayList 通过在必要时自动调整自身大小来实现无限容量。因此,它仍必须将元素复制到新位置。唯一的区别是它是在幕后完成的,而不是要求程序员这样做。

    【讨论】:

      猜你喜欢
      • 2012-07-28
      • 1970-01-01
      • 2015-10-30
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      • 2013-05-17
      • 2013-04-19
      • 1970-01-01
      相关资源
      最近更新 更多