为什么Java中的LinkedList不是真正的链表?

时间:2013-02-11 16:57:00

标签: java linked-list

根据定义,Linked List是一个列表,它的每个元素引用下一个元素(如果我们正在谈论双链表,那么前面的元素。) http://en.wikipedia.org/wiki/Linked_list

然而,在Java中,LinkedList实现了List,Queue,Deque等。 http://docs.oracle.com/javase/6/docs/api/java/util/LinkedList.html

您无法在LinkedList中找到一个方法,它为您提供列表中的下一个或上一个对象,您可以做的最好的方法是获取Iterator并获取对象。我的问题是为什么Java已经调用了这个数据结构LinkedList,而它不是真正的链表?链接列表可以用Java实现,如下所示:

Public class MyLinkedList{
 public int value;
 public MyLinkedList next;
}

7 个答案:

答案 0 :(得分:6)

  

您无法在LinkedList中找到一个方法,该方法为您提供列表中的下一个或上一个对象

不,这完全合适。 “列表中的下一项”的概念在列表中没有意义。它对列表中的节点非常有意义,但这不是Java API公开的内容。它当然是内部存在的 - 只是没有暴露。如果要遍历列表,则使用迭代器。您仍然可以在开头或结尾添加,从开头或结尾删除,以及从迭代器添加/删除。

虽然您确实可以将“节点”和“列表”的概念混淆为您建议的示例代码,但我认为这通常不是一个好主意。

换句话说:你想要实现是什么导致你出现问题?我相信你应该能够使用公共API做你想做的事 - 你可能根本没有注意到它。

答案 1 :(得分:5)

  

我的问题是为什么Java调用了这个数据结构LinkedList,而它不是真正的链表?

因为它的实现是一个链表。来自the documentation

  

ListDeque接口的双链表实现。实现所有可选列表操作,并允许所有元素(包括null)。

LinkedList是通过链接列表实现的ListArrayList是使用数组等实现的List。您选择哪一个可能对于运行时特征。例如,来自LinkedList文档:

  

所有操作的执行都与双向链表一样。索引到列表中的操作将从开头或结尾遍历列表,以较接近指定索引为准。

例如,您知道next来自Iteratoriterator的{​​{1}}将非常有效,但是listIterator by index将涉及遍历。

答案 2 :(得分:3)

集合是链表还是数组列表与其合同无关,而与其实现有关。 LinkedList确实是实施的链接列表,合同是java.util.List

它显示的不是它的API,而是它的空间/时间复杂性特征,任何熟悉链表的人都可以轻松预测。

作为参考,这是LinkedList节点的实际实现,非常符合您的期望:

957  private static class Node<E> {
958 E item;
959 Node<E> next;
960 Node<E> prev;
962 Node(Node<E> prev, E element, Node<E> next) {
963 this.item = element;
964 this.next = next;
965 this.prev = prev;
966 }
967 }

答案 3 :(得分:1)

除了其他人的正确答案之外,如果接口的底层实现是链接列表,则实现对象将有一个方法来获取列表中的下一个项目。该方法不作为合同的一部分公开。

实现是链表的事实会影响List合同的各种方法的Big-O性能。

答案 4 :(得分:0)

  

然而,在Java中,LinkedList实现了List,Queue,Deque等。

根据API,LinkedList实现了这些接口,因此可以使用任何这些结构。

答案 5 :(得分:0)

当我读完你的问题时,我感觉你没有区分链表的概念和链表的实现。

您的示例代码很好地演示了链表的概念,但这并不意味着它是实现链表的唯一方法或最佳方式。我相信您可以使用内置的LinkedList类执行标准链接列表所需的任何操作,尽管您可能会在数据结构类或教科书中看到一组不熟悉的API。

所以基本上,只要你能在O(1)时间内实现插入操作,在O(1)时间内删除操作,在O(n)时间内进行搜索操作等,它就是链表。与其他数据结构(如数组)的时间复杂性形成对比。

内置LinkedList没有直接提供next操作,而是通过其迭代器提供。这只是Java语言的设计决策,因为您可能会受益于Iterator pattern

Java是一种典型的面向对象语言,其主要特征之一是Abstraction

答案 6 :(得分:0)

所以我不知道@Marko从哪里读取该实现,但是1.8 jdk中的实现却大不相同。

首先,声明的第一个变量是:

 transient int size = 0;

每当将节点添加到列表时,该值就会增加。这意味着列表中存在Integer.MAX_VALUE(2147483647)节点的固有限制。在现代世界中,这个数字并没有看起来那么大。问题不在于我们没有一个真正的链接列表(创建起来很简单),而是对于所有第3方库,他们很可能不会考虑这一点,然后整个库都无法使用。