LinkedList principle introduction

A, LinkedList overview

  1. LinkedList is a doubly linked list to achieve List
  2. LinkedList not thread-safe
  3. Element allows LinkedList is null, allowing repeat element
  4. LinkedList is implemented based on the list, so high insertion deleted efficiency, low search efficiency (although there is an accelerated action)
  5. LinkedList is based on the realization of the list, so there is no problem of insufficient capacity, so there is no expansion method
  6. LinkedList also achieved queue stack and method of operation, and therefore may be used as a stack, and queues used deque

Two, LinkedList analysis

LinkedList storage structure

LinkedList is a doubly-linked list data structure consisting of

public class LinkedList{
// 元素个数
transient int size = 0;
/**
指向第一个节点的指针
不变性:
1. 如果first = null,则last=null
2. 如果first.prev == null,则first.item != null
*/
transient Node<E> first;
/**
指向最后一个节点的指针
不变性:
1. 如果first = null,则last = null
2. 如果last.next == null,则last.item != null
*/
transient Node<E> last;
private static class Node<E> { E item;
Node<E> next; // 下一个Node的引用
Node<E> prev; // 上一个Node的引用
Node(Node<E> prev, E element, Node<E> next) { this.item = element;
this.next = next; this.prev = prev;
}
}
/**
创建一个空list
* */
public LinkedList() {
}
public LinkedList(Collection<? extends E> c) { this();
addAll(c);
}
}

 

Adding elements

Add from the head

// 从头插入
public void addFirst(E e) {
linkFirst(e);
}
private void linkFirst(E e) { final Node<E> f = first;
final Node<E> newNode = new Node<>(null, e, f); first = newNode;
if (f == null) // 当前List中没有元素,size=0
last = newNode; else
f.prev = newNode; size++;
modCount++;
}

For appending

public boolean add(E e) { linkLast(e);
return true;
}
public void addLast(E e) { linkLast(e);
}
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null); last = newNode;
if (l == null)// 当前List中没有元素,size=0
first = newNode; else
l.next = newNode; size++;
modCount++;
}

Delete Node

Delete from the head

// 移除首节点,并返回该节点的元素值
public E remove() { return removeFirst();
}
public E removeFirst() { final Node<E> f = first; if (f == null)
throw new NoSuchElementException(); return unlinkFirst(f);
}
// 删除首节点f
private E unlinkFirst(Node<E> f) { final E element = f.item; final Node<E> next = f.next; f.item = null;
f.next = null; // help GC first = next;
if (next == null) // size=1 last = null;
else
next.prev = null; size--;
modCount++; return element;
}

Removed from the tail

public E removeLast() { final Node<E> l = last; if (l == null)
throw new NoSuchElementException(); return unlinkLast(l);
}

private E unlinkLast(Node<E> l) { final E element = l.item; final Node<E> prev = l.prev; l.item = null;
l.prev = null; // help GC last = prev;
if (prev == null) // size=1 first = null;
else
prev.next = null; size--;
modCount++; return element;
}

Removed from the index

public E remove(int index) { checkElementIndex(index);// 检查索引index范围return unlink(node(index));
}
E unlink(Node<E> x) {
final E element = x.item; final Node<E> next = x.next; final Node<E> prev = x.prev;
if (prev == null) {// x为首节点first = next;
} else {
prev.next = next; x.prev = null;
}
if (next == null) {// x为尾节点last = prev;
} else {
next.prev = prev; x.next = null;
}
x.item = null; size--; modCount++; return element;
}

Obtaining node data

Obtain header data

// 获取首节点的数据
public E getFirst() {
final Node<E> f = first; if (f == null)
throw new NoSuchElementException(); return f.item;
}

Data acquisition tail

// 获取尾节点的数据
public E getLast() {
final Node<E> l = last; if (l == null)
throw new NoSuchElementException(); return l.item;
}

Obtaining the index node data

// 获取索引对应节点的数据
public E get(int index) { checkElementIndex(index); return node(index).item;
}
// 类似折半查找
Node<E> node(int index) {
if (index < (size >> 1)) {// 从前半部分查找
Node<E> x = first;
for (int i = 0; i < index; i++) x = x.next;
return x;
} else {// 从后半部分查找
Node<E> x = last;
for (int i = size - 1; i > index; i--) x = x.prev;
return x;
}
}

Third, the summary: To compare the ArrayList and LinkedList

ArrayList sequence insertion speed will be faster, because ArrayList array is implemented based on, new arrays are well in advance, as long as the plug to a specified position data like

LinkedList is different, each insertion order when a new LinkedList objects will come out, if the object is relatively large, then the new president a little time bound, plus some operating reference assignment, the order of insertion necessarily slower than ArrayList LinkedList

Traversing ArrayList efficiency will be higher than the efficiency of traversing some of LinkedList

LinkedList do insert, delete, when slow in addressing the fast only need to change before and after the Node reference address

ArrayList do insert, delete, when in slow bulk copy array elements in the addressing fast

If it is determined insert, delete elements in the former half, then use LinkedList

If it is determined insert, delete elements in position by comparison, consider using ArrayList

If you are unsure insert, delete Where is it? Recommended LinkedList,

As a whole LinkedList insert, delete efficiency is relatively stable, there is no more back sooner ArrayList this case

Secondly insert elements when the mess it will be carried out once ArrayList expansion, and expansion of the underlying array ArrayList is both time consuming and space-consuming operation

Published 682 original articles · won praise 1391 · Views 1.71 million +

Guess you like

Origin blog.csdn.net/itcast_cn/article/details/104795099