LinkedList源码阅读分析
LinkedList 是一个继承于AbstractSequentialList 的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。LinkedList 实现 List 接口,能对它进行队列操作。LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。LinkedList 实现了Cloneable 接口,即覆盖了函数clone(),能克隆。LinkedList 实现java.io.Serializable 接口,这意味着LinkedList支持序列化,能通过序列化去传输。LinkedList 是非同步 的
1.2 LinkedList源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 复制代码 隐藏代码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; .
1.2.1 主要构造方法 (1). LinkedList() 1 2 复制代码 隐藏代码public LinkedList () { }
LinkedList 的无参构造就是构造一个空的list集合
(2). LinkedList(Collection<? extends E> c) 1 2 3 4 复制代码 隐藏代码public LinkedList (Collection<? extends E> c) { this (); addAll(c); }
构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。
1.2.2 主要内部类 典型的双链表结构。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 复制代码 隐藏代码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; } }
LinkedList 是通过双向链表实现的,而双向链表就是通过Node类来实现的,Node类中通过item变量存储当前元素,通过next变量指向当前节点的下一个节点,通过prev变量指向当前节点的上一个节点。
1.2.3 LinkedList增加节点 (1). add(E e) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 复制代码 隐藏代码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++; }
第一步,获取链表的最后一个节点
第二步,创建一个新节点
第三步,使新的一个节点为最后一个节点
第四步,如果最后一个节点为null,则表示链表为空,则将newNode赋值给first节点;否则尾节点的last指向 newNode
(2). add(int index, E element) 在指定位置插入元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 复制代码 隐藏代码public void add (int index, E element) { checkPositionIndex(index); if (index == size) linkLast(element); else linkBefore(element, node(index)); } private void checkPositionIndex (int index) { if (!isPositionIndex(index)) throw new IndexOutOfBoundsException (outOfBoundsMsg(index)); } private boolean isPositionIndex (int index) { return index >= 0 && index <= size; } 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++; } void linkBefore (E e, Node<E> succ) { final Node<E> pred = succ.prev; final Node<E> newNode = new Node <>(pred, e, succ); succ.prev = newNode; if (pred == null ) first = newNode; else pred.next = newNode; size++; modCount++; } 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; } }
(3). addAll(Collection<? extends E> c) 1 2 3 4 复制代码 隐藏代码public boolean addAll (Collection<? extends E> c) { return addAll(size, c); }
(4).addAll(int index, Collection<? extends E> c) 在指定位置添加一个集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 复制代码 隐藏代码public boolean addAll (int index, Collection<? extends E> c) { checkPositionIndex(index); Object[] a = c.toArray(); int numNew = a.length; if (numNew == 0 ) return false ; Node<E> pred, succ; if (index == size) { succ = null ; pred = last; } else { succ = node(index); pred = succ.prev; } for (Object o : a) { @SuppressWarnings("unchecked") E e = (E) o; Node<E> newNode = new Node <>(pred, e, null ); if (pred == null ) first = newNode; else pred.next = newNode; pred = newNode; } if (succ == null ) { last = pred; } else { pred.next = succ; succ.prev = pred; } size += numNew; modCount++; return true ; }
(5). addFirst(E e) 从队列首添加元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 复制代码 隐藏代码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 ) last = newNode; else f.prev = newNode; size++; modCount++; }
(6). addLast(E e) 从队尾添加元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 复制代码 隐藏代码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 ) first = newNode; else l.next = newNode; size++; modCount++; }
1.2.3 LinkedList删除节点 (1). remove() 从队首删除元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 复制代码 隐藏代码public E remove () { return removeFirst(); } public E removeFirst () { final Node<E> f = first; if (f == null ) throw new NoSuchElementException (); return unlinkFirst(f); } private E unlinkFirst (Node<E> f) { final E element = f.item; final Node<E> next = f.next; f.item = null ; f.next = null ; first = next; if (next == null ) last = null ; else next.prev = null ; size--; modCount++; return element; }
(2). remove(int index) 删除指定索引位置元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 复制代码 隐藏代码public E remove (int index) { checkElementIndex(index); return unlink(node(index)); } private void checkElementIndex (int index) { if (!isElementIndex(index)) throw new IndexOutOfBoundsException (outOfBoundsMsg(index)); } private boolean isElementIndex (int index) { return index >= 0 && index < size; } 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; } } 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 ) { first = next; } else { prev.next = next; x.prev = null ; } if (next == null ) { last = prev; } else { next.prev = prev; x.next = null ; } x.item = null ; size--; modCount++; return element; }
(3). remove(Object o) 根据元素删除
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 复制代码 隐藏代码public boolean remove (Object o) { if (o == null ) { for (Node<E> x = first; x != null ; x = x.next) { if (x.item == null ) { unlink(x); return true ; } } } else { for (Node<E> x = first; x != null ; x = x.next) { if (o.equals(x.item)) { unlink(x); return true ; } } } return false ; }
(4). removeFirst() 删除首节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 复制代码 隐藏代码public E removeFirst () { final Node<E> f = first; if (f == null ) throw new NoSuchElementException (); return unlinkFirst(f); } private E unlinkFirst (Node<E> f) { final E element = f.item; final Node<E> next = f.next; f.item = null ; f.next = null ; first = next; if (next == null ) last = null ; else next.prev = null ; size--; modCount++; return element; }
(5). removeLast() 删除尾结点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 复制代码 隐藏代码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 ; last = prev; if (prev == null ) first = null ; else prev.next = null ; size--; modCount++; return element; }
(6). removeFirstOccurrence(Object o) 删除指定元素第一次出现在该列表中(遍历从头部到尾部列表时)。如果列表中不包含该元素,它是不变的。
1 2 3 复制代码 隐藏代码public boolean removeFirstOccurrence (Object o) { return remove(o); }
(7).removeLastOccurrence(Object o) 删除此列表中最后一次出现的指定元素(从头到尾遍历列表时)。如果列表不包含该元素,则它保持不变。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 复制代码 隐藏代码public boolean removeLastOccurrence (Object o) { if (o == null ) { for (Node<E> x = last; x != null ; x = x.prev) { if (x.item == null ) { unlink(x); return true ; } } } else { for (Node<E> x = last; x != null ; x = x.prev) { if (o.equals(x.item)) { unlink(x); return true ; } } } return false ; }
1.2.4 LinkedList修改节点 (1) set(int index, E element) 根据索引修改节点
1 2 3 4 5 6 7 8 9 10 11 12 复制代码 隐藏代码public E set (int index, E element) { checkElementIndex(index); Node<E> x = node(index); E oldVal = x.item; x.item = element; return oldVal; }
1.2.5 LinkedList查找节点 (1). get(int index) 根据索引查找节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 复制代码 隐藏代码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; } }
(2). getFirst() 获取首节点
1 2 3 4 5 6 复制代码 隐藏代码public E getFirst () { final Node<E> f = first; if (f == null ) throw new NoSuchElementException (); return f.item; }
(3). getLast() 获取尾结点
1 2 3 4 5 6 复制代码 隐藏代码 public E getLast () { final Node<E> l = last; if (l == null ) throw new NoSuchElementException (); return l.item; }
1.3 LinkedList作为栈使用 1 2 3 4 5 6 7 复制代码 隐藏代码public void push (E e) { addFirst(e); } public E pop () { return removeFirst(); }
栈的特性是LIFO(Last In First Out),所以作为栈使用也很简单,添加删除元素都只操作队列首节点即可。
1.4 LinkedList总结 (1)LinkedList 是一个以双链表 实现的List;
(2)LinkedList 还是一个双端队列,具有队列、双端队列、栈 的特性;
(3)LinkedList 在队列首尾添加、删除元素 非常高效,时间复杂度为O(1);
(4)LinkedList 在中间添加、删除元素 比较低效,时间复杂度为O(n);
(5)LinkedList 不支持随机访问,所以访问非队列首尾的元素比较低效;
(6)LinkedList 在功能上等于ArrayList + ArrayDeque;
备忘:
数组 : 是一种线性 数据结构,使用一组连续 的内存空间存储一组具有相同类型 的数据。
线性 ,表示没有分叉,任意元素的前后元素最多只有一个,同样是线性结构的还有链表、队列等。
连续 ,它在内存空间中的存储是连续的,不间断的,前后两个元素紧挨着,不存在间隙。
相同类型 ,数组中存储的元素的类型一定是相同的,当然,在Java中,你可以使用Object代表所有类型,本质上,它们依然是相同类型。
正是有了上面三个特性,才使得数组具有了随机访问 的特性
链表 :它也是一种线程数据结构 ,与数组不同的是,它在内存空间中不一定是顺序存储 的,为了保证链表中元素的连续性 ,一般使用一个指针 来找到下一个元素
链表不具有随机访问 的特性,在链表中根据索引来查找元素只能从头开始(单链表 )【双链表可从首尾查找元素】,它的时间复杂度是O(n)。
如果在单链表的基础上再增加一个前驱指针(指向前一个元素的指针),就变成了双向链表
LinkedList就是典型的双向链表结构,双向链表既可以当作队列使用,又可以当作栈来使用,非常方便 。
队列 :所谓队列,其实跟现实中的排队是一样的,其中的元素从一端进入,从另一端出去,英文叫做:First In,First Out,简写FIFO。【先进先出】
栈 :栈,它是与队列表现完全相反的数据结构,它的元素是先进的后出来。【先进后出】
__END__