为什么我们可以向 java LinkedList 添加空元素?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21206038/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why can we add null elements to a java LinkedList?
提问by Jamal Khan
I'm using java.util implementation of a linked list. I was wondering why it allows us to add null elements, and we can even iterate through them?
我正在使用链表的 java.util 实现。我想知道为什么它允许我们添加空元素,我们甚至可以遍历它们?
Doesn't that defeat the point of a linked list, where we have an element that points to the next element, and the conventional implementation of a linked list would break if we added null elements and tried to iterate over it.
这不会破坏链表的观点,我们有一个元素指向下一个元素,如果我们添加空元素并尝试对其进行迭代,链表的传统实现就会中断。
回答by zmb
Looking at the Java 7 sources, LinkedList
is implemented as a series of nodes.
查看 Java 7 源代码,它LinkedList
是作为一系列节点实现的。
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
Each node has a reference to the previous node and next node, as well as an item
. When you insert a null value into the list, you're inserting a node with a null
value for item
, but the next
and prev
pointers are non-null.
每个节点都有对上一个节点和下一个节点的引用,以及一个item
. 当您在列表中插入一个空值时,您将插入一个null
值为的节点item
,但next
和prev
指针是非空的。
回答by ChrisCantrell
Conceptually, the Java collections hold pointers to objects and not the objects themselves. When you see List<String>
think List<Pointer-to-String>
. You can store multiple copies of the same string-address in a collection. Multiple collections can share the same object pointers, and you can store the null pointer in a collection.
从概念上讲,Java 集合持有指向对象的指针,而不是对象本身。当你看到List<String>
想List<Pointer-to-String>
。您可以在集合中存储相同字符串地址的多个副本。多个集合可以共享相同的对象指针,您可以将空指针存储在一个集合中。
You are thinking of a "conventional" implementation that adds the pointers to the structures themselves. Java separates the details of the "links" from your code by introducing a "header" object that contains pointers to one another AND a pointer to the object you put in. This pointer to your object can be null. Internally, the LinkedList code uses a null pointer in the "header" object to designate the end of the list. This extra pointer is a tad slower since you have to chase it to get to the "payload". But it allows polymorphism (4 paragraphs down).
您正在考虑将指针添加到结构本身的“常规”实现。Java 通过引入一个包含指向彼此的指针和指向您放入的对象的指针的“头”对象,将“链接”的细节与您的代码分开。指向您的对象的指针可以为空。在内部,LinkedList 代码使用“header”对象中的空指针来指定列表的结尾。这个额外的指针有点慢,因为你必须追逐它才能到达“有效载荷”。但它允许多态性(向下 4 段)。
We usually don't think of the details of a List implementation at all. We code to the "List" interface. The List allows us to insert and remove pointers to objects and access these pointers to objects by index. The pointers can be null.
我们通常根本不会考虑 List 实现的细节。我们编码到“列表”界面。List 允许我们插入和删除指向对象的指针,并通过索引访问这些指向对象的指针。指针可以为空。
The LinkedList is quick with inserts/removes but slower with random access (it has to chase the "header" pointers). The ArrayList is quick with random access but slow with inserts/removes (it has to copy memory around). You write your code to the "List" interface and pick an implementation based on your use. And you can change implementation later without changing your code that uses the List interface.
LinkedList 的插入/删除速度很快,但随机访问速度较慢(它必须追逐“头”指针)。ArrayList 在随机访问时很快,但在插入/删除时很慢(它必须复制内存)。您将代码写入“列表”接口并根据您的使用选择一个实现。您可以稍后更改实现,而无需更改使用 List 接口的代码。
Note in the C++ standard-template library a std::list<std::string>
makes a collection of objects themselves (not pointers to objects), and you can't insert nulls. A Java-like collection would be a std::list<std::string *>
, which is a collection of pointers that CAN be null.
请注意,在 C++ 标准模板库中, astd::list<std::string>
本身是一个对象集合(不是指向对象的指针),并且不能插入空值。一个类似于 Java 的集合是 a std::list<std::string *>
,它是一个可以为空的指针集合。
Collecting "pointers" has the advantage of allowing polymorphism. If I collect objects and not pointers then I can't put a SuperString into a collection of Strings because the code actually copies the structure into its own memory. SuperString is too big for a String slot. But pointers are all the same size; I can put a pointer to a SuperString into a collection of String pointers just fine.
收集“指针”的优点是允许多态性。如果我收集对象而不是指针,那么我不能将 SuperString 放入字符串集合中,因为代码实际上将结构复制到自己的内存中。SuperString 对于 String 插槽来说太大了。但是指针的大小都是一样的;我可以将指向 SuperString 的指针放入 String 指针集合中就好了。