简体   繁体   English

Java API中LinkedList类中的“标题”

[英]The “header” in the LinkedList class in Java API

In reading the LinkedList doc, I am a little puzzled by the uses of "header". 在阅读LinkedList文档时,我对“标头”的使用感到有些困惑。 Normally, the header is the first node in a linkedList. 通常,标头是linkedList中的第一个节点。 But here it looks like the 'header' is a dummy node in the list and it points to the first and last nodes of the list, thus making the LinkedList a circular one. 但是在这里,看起来“标题”是列表中的一个虚拟节点,它指向列表的第一个和最后一个节点,因此使LinkedList成为一个循环节点。 Is that true? 真的吗?

private transient Entry<E> header = new Entry<E>(null, null, null);
public LinkedList() {
    header.next = header.previous = header;
}

public E getFirst() {
    if (size==0)
        throw new NoSuchElementException();

    return header.next.element;
}

public E getLast()  {
    if (size==0)
        throw new NoSuchElementException();

    return header.previous.element;
}

public E removeFirst() {
    return remove(header.next);
}

But here it looks like the 'header' is a dummy node in the list and it points to the first and last nodes of the list 但是这里看起来“ header”是列表中的一个虚拟节点,它指向列表的第一个和最后一个节点

That much is true 那是真的

thus making the LinkedList a circular one. 因此使LinkedList成为一个循环列表。

That's not exactly true: structurally, the list is indeed circular, because the header "loops" it around. 这不是完全正确的:从结构上讲,列表确实是循环的,因为标头将其“循环”。 That is only an implementation detail, a common trick that lets you avoid declaring two things ( header and tailPiece ) instead of one. 那只是实现细节,这是一个常见的技巧,可让您避免声明两个东西( headertailPiece )而不是一个。 The fact that the same entry is used for both ends by itself is insufficient to make the list circular: there is no way for you to loop around the last node "from the outside", because the count prevents you from doing so. 两端都使用相同的条目这一事实不足以使列表循环:没有办法让您“从外部”在最后一个节点周围循环,因为count阻止您这样做。

You're right. 你是对的。 header stores references to both the head and tail of the list. header存储对列表开头和结尾的引用。 This helps in reducing cost of operations involving delete/add/view for both the ends of the list. 这有助于减少涉及列表两端的删除/添加/查看的操作成本。

With the availability of references to both the ends, operations like getFirst , getLast , removeFirst , removeLast , addFirst , addLast etc. don't require list traversal. 随着两端引用的可用性,诸如getFirstgetLastremoveFirstremoveLastaddFirstaddLast等操作不需要列表遍历。

A circular list is a cheap way to avoid storing both head and tail pointers in the top-level structure. 循环列表是一种避免在顶部结构中同时存储头和尾指针的廉价方法。 I don't know about Java's LinkedList implementation, but this is certainly a trick pulled in eg the GCC implementation of std::list . 我不知道Java的LinkedList实现,但这确实是把技巧引入例如std::list的GCC实现中。

The implementation of LinkedList is using what's called s sentinel node. LinkedList的实现使用所谓的sentinel节点。 They've chosen to use one sentinel for both head and tail; 他们选择对头和尾巴使用一个哨兵。 other implmentations will use two separate sentinels. 其他实现将使用两个单独的标记。

In either case, the use of sentinels allow the rest of the implementation code to not deal with the null case. 无论哪种情况,使用前哨都使其余的实现代码不处理空值情况。 For example, consider adding a node. 例如,考虑添加一个节点。 Without a sentinel: 没有哨兵:

Node newNode = ...;
if (header == null) {
  header = newNode;
  tail = newNode;
} else {
  newNode.previous = tail;
  tail.next = newNode;
  tail = newNode;
}

With the sentinel: 与前哨:

Node newNode = ...;
newNode.previous = sentinel.previous;
newNode.next = sentinel;
sentinel.previous = newNode;

Here's the Wikipedia article on Sentinel Nodes . 这是有关Sentinel NodesWikipedia文章

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

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