基本介绍
Linkedlist基于链表的动态数组(双向链表): 可以被当作堆栈(后进先出)、队列(先进先出)或双端队列进行操作。 数据添加删除效率高,只需要改变指针指向即可,但是访问数据的平均效率低,需要对链表进行遍历。 非同步,线程不安全。 支持null元素、有顺序、元素可以重复 不要使用普通for循环去遍历LinkedList,使用迭代器或者foreach循环(foreach循环的原理就是迭代器)去遍历LinkedList即可: 这种方式是直接按照地址去找数据的,将会大大提升遍历LinkedList的效率。
源码分析
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable { //实际大小 transient int size = 0; //头节点 transient Node<E> first; //尾节点 transient Node<E> last; public LinkedList() { } public LinkedList(Collection<? extends E> c) { this(); addAll(c); } //双向链表 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; } } //添加在头节点 private void linkFirst(E e) { //旧头节点 final Node<E> f = first; //新节点的next指向旧头节点 final Node<E> newNode = new Node<>(null, e, f); //头节点改成新节点 first = newNode; //如果旧头节点为null,表示空链表,尾节点也指向新节点 if (f == null) last = newNode; //旧头节点的prev指向新节点 else f.prev = newNode; size++; modCount++; } //添加到链表尾部 public boolean add(E e) { linkLast(e); return true; } void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; } public void add(int index, E element) { //检查index是否合理 checkPositionIndex(index); //如果index是size,则添加在尾部 if (index == size) linkLast(element); else linkBefore(element, node(index)); } //查找index处的节点 Node<E> node(int index) { // assert isElementIndex(index); //如果index在左半边,则从头遍历(提到查找效率) if (index < (size >> 1)) { Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { //如果index在右半边,则从尾遍历(提到查找效率) Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } } void linkBefore(E e, Node<E> succ) { // assert succ != null; //旧节点的前一个节点 final Node<E> pred = succ.prev; //将新节点设置为:prev为旧节点的前一个节点,next为旧节点 final Node<E> newNode = new Node<>(pred, e, succ); //旧节点的prev指向新节点 succ.prev = newNode; //旧节点的前一个节点是空,表示旧节点是头节点,则重设头节点 if (pred == null) first = newNode; //旧节点的前一个节点的next指向新节点 else pred.next = newNode; size++; modCount++; } public E removeFirst() { final Node<E> f = first; if (f == null) throw new NoSuchElementException(); return unlinkFirst(f); } private E unlinkFirst(Node<E> f) { // assert f == first && f != null; final E element = f.item; final Node<E> next = f.next; f.item = null; f.next = null; // help GC first = next; if (next == null) last = null; else next.prev = null; size--; modCount++; return element; } public E remove(int index) { checkElementIndex(index); return unlink(node(index)); } E unlink(Node<E> x) { // assert x != null; final E element = x.item; //要删除元素的后一个 final Node<E> next = x.next; //要删除元素的前一个 final Node<E> prev = x.prev; //如果前是空,表示删除头元素,后变成头元素 if (prev == null) { first = next; } else { //前的下一个变成后 prev.next = next; x.prev = null; //帮助GC } //如果后是空,表示删除尾元素,前变成尾元素 if (next == null) { last = prev; } else { //后的上一个变成前 next.prev = prev; x.next = null; //帮助GC } x.item = null; //帮助GC size--; modCount++; return element; } public E getFirst() { final Node<E> f = first; if (f == null) throw new NoSuchElementException(); return f.item; } public E get(int index) { checkElementIndex(index); return node(index).item; } }
来源:https://www.cnblogs.com/loveer/p/11533637.html