LinkedList源码解析——JDK1.8
2017-07-27 13:15
555 查看
1、LinkedList介绍
LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。LinkedList 实现 List 接口,能对它进行队列操作。
LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。
LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。
LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。
LinkedList 是非同步的。
2、关键点
LinkedList的本质是双向链表。LinkedList继承于AbstractSequentialList,并且实现了Dequeue接口。
LinkedList包含三个重要的成员:first、last 和 size。
first指向链表的第一个节点。
last 指向链表的最后一个节点。
size 是双向链表中节点的个数。
3、节点Node结构
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; } }
4、构造函数
//构造一个空链表 public LinkedList() { } //构建一个包含指定集合c的列表 public LinkedList(Collection<? extends E> c) { this(); addAll(c); }
5、add添加元素
LinkedList提供了头插addFirst(E e)、尾插addLast(E e)、add(E e)、addAll(Collection//头插,在列表首部插入节点值e public void addFirst(E e) { linkFirst(e); } //头插,也就是将节点值为e的节点设置为链表首节点 private void linkFirst(E e) { final Node<E> f = first; //构建一个prev值为null,节点值为e,next值为f的新节点newNode final Node<E> newNode = new Node<>(null, e, f); //将newNode作为首节点 first = newNode; //如果原首节点为null,即原链表为null,则链表尾节点也设置为newNode if (f == null) last = newNode; else //否则,原首节点的prev设置为newNode f.prev = newNode; size++; modCount++; } //尾插,在列表尾部插入节点值e,该方法等价于add() public void addLast(E e) { linkLast(e); } //尾插,在列表尾部插入节点值e public boolean add(E e) { linkLast(e); return true; } //尾插,即将节点值为e的节点设置为链表的尾节点 void linkLast(E e) { final Node<E> l = last; //构建一个prev值为l,节点值为e,next值为null的新节点newNode final Node<E> newNode = new Node<>(l, e, null); //将newNode作为尾节点 last = newNode; //如果原尾节点为null,即原链表为null,则链表首节点也设置为newNode if (l == null) first = newNode; else //否则,原尾节点的next设置为newNode l.next = newNode; size++; modCount++; } //中间插入,在非空节点succ之前插入节点值e void linkBefore(E e, Node<E> succ) { // assert succ != null; final Node<E> pred = succ.prev; //构建一个prev值为succ.prev,节点值为e,next值为succ的新节点newNode final Node<E> newNode = new Node<>(pred, e, succ); //设置newNode为succ的前节点 succ.prev = newNode; //如果succ.prev为null,即如果succ为首节点,则将newNode设置为首节点 if (pred == null) first = newNode; else //如果succ不是首节点 pred.next = newNode; size++; modCount++; } /** * 按照指定collection的迭代器所返回的元素顺序,将该Collection中的所有元素添加到此链表的尾部 * 如果指定的集合添加到链表的尾部的过程中,集合被修改,则该插入过程的后果是不确定的。 * 一般这种情况发生在指定的集合为该链表的一部分,且其非空。 * @throws NullPointerException 指定集合为null */ public boolean addAll(Collection<? extends E> c) { return addAll(size, c); } //从指定的位置开始,将指定Collection中的所有元素插入到此链表中, //新元素的顺序为指定Collection的迭代器所返回的元素顺序。 public boolean addAll(int index, Collection<? extends E> c) { checkPositionIndex(index); //index >= 0 && index <= size Object[] a = c.toArray(); int numNew = a.length; if (numNew == 0) return false; //succ指向当前需要插入节点的位置,pred指向其前一个节点 Node<E> pred, succ; if (index == size) { //说明在列表尾部插入集合元素 succ = null; pred = last; } else { //得到索引index所对应的节点 succ = node(index); pred = succ.prev; } //指定collection中的所有元素依次插入到此链表中指定位置的过程 for (Object o : a) { @SuppressWarnings("unchecked") E e = (E) o; //将元素值e,前继节点pred“封装”为一个新节点newNode Node<E> newNode = new Node<>(pred, e, null); if (pred == null) //如果原链表为null,则新插入的节点作为链表首节点 first = newNode; else pred.next = newNode; pred = newNode; //pred指针向后移动,指向下一个需插入节点位置的前一个节点 } //集合元素插入完成后,与原链表index位置后面的子链表链接起来 if (succ == null) { //说明之前是在列表尾部插入的集合元素 last = pred; //pred指向的是最后插入的那个节点 } else { pred.next = succ; succ.prev = pred; } size += numNew; modCount++; return true; } //将指定的元素(E element)插入到列表的指定位置(index) public void add(int index, E element) { checkPositionIndex(index); //index >= 0 && index <= size if (index == size) linkLast(element); //尾插入 else linkBefore(element, node(index)); //中间插入 }
6、remove删除元素
//移除首节点,并返回该节点的元素值 public E removeFirst() { final Node<E> f = first; if (f == null) throw new NoSuchElementException(); return unlinkFirst(f); } //删除非空的首节点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; //将原首节点的next节点设置为首节点 if (next == null) //如果原链表只有一个节点,即原首节点,删除后,链表为null last = null; else next.prev = null; size--; modCount++; return element; } //移除尾节点,并返回该节点的元素值 public E removeLast() { final Node<E> l = last; if (l == null) throw new NoSuchElementException(); return unlinkLast(l); } //删除非空的尾节点l private E unlinkLast(Node<E> l) { // assert l == last && l != null; final E element = l.item; final Node<E> prev = l.prev; l.item = null; l.prev = null; // help GC last = prev; //将原尾节点的prev节点设置为尾节点 if (prev == null) //如果原链表只有一个节点,则删除后,链表为null first = null; else prev.next = null; size--; modCount++; return element; } //移除此列表中指定位置上的元素 public E remove(int index) { checkElementIndex(index); //index >= 0 && index < size return unlink(node(index)); } //删除非空节点x 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; } if (next == null) { //如果被删除节点为尾节点 last = prev; } else { next.prev = prev; x.next = null; } x.item = null; // help GC size--; modCount++; return element; } //移除列表中首次出现的指定元素(如果存在),LinkedList中允许存放重复的元素 public boolean remove(Object o) { //由于LinkedList中允许存放null,因此下面通过两种情况来分别处理 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; } //清除列表中所有节点 public void clear() { 、、将所有的引用置null,让GC回收对象 for (Node<E> x = first; x != null; ) { Node<E> next = x.next; x.item = null; x.next = null; x.prev = null; x = next; } first = last = null; size = 0; modCount++; }
7、set修改元素
//替换指定索引位置节点的元素值,并返回旧值 public E set(int index, E element) { checkElementIndex(index); //index >= 0 && index < size Node<E> x = node(index); E oldVal = x.item; x.item = element; return oldVal; }
8、get查找元素
LinkedList提供了getFirst()、getLast()、contains(Object o)、get(int index)、indexOf(Object o)、lastIndexOf(Object o)这些查找元素的方法。//返回列表首节点元素值 public E getFirst() { final Node<E> f = first; if (f == null) //如果首节点为null throw new NoSuchElementException(); return f.item; } //返回列表尾节点元素值 public E getLast() { final Node<E> l = last; if (l == null) //如果尾节点为null throw new NoSuchElementException(); return l.item; } //判断列表中是否包含有元素值o, //返回true当列表中至少存在一个元素值e,使得(o==null?e==null:o.equals(e)) public boolean contains(Object o) { return indexOf(o) != -1; } //返回指定索引处的元素值 public E get(int index) { checkElementIndex(index); //index >= 0 && index < size return node(index).item; //node(index)返回指定索引位置index处的节点 } //返回指定索引位置的节点 Node<E> node(int index) { // assert isElementIndex(index); //折半思想,当index < size/2时,从列表首节点向后查找 if (index < (size >> 1)) { Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { //当index >= size/2时,从列表尾节点向前查找 Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } } //正向查找,返回LinkedList中元素值Object o第一次出现的位置,如果元素不存在,则返回-1 public int indexOf(Object o) { int index = 0; //由于LinkedList中允许存放null,因此下面通过两种情况来分别处理 if (o == null) { for (Node<E> x = first; x != null; x = x.next) { //顺序向后 if (x.item == null) return index; index++; } } else { for (Node<E> x = first; x != null; x = x.next) { if (o.equals(x.item)) return index; index++; } } return -1; } //逆向查找,返回LinkedList中元素值Object o最后一次出现的位置,如果元素不存在,则返回-1 public int lastIndexOf(Object o) { int index = size; //由于LinkedList中允许存放null,因此下面通过两种情况来分别处理 if (o == null) { for (Node<E> x = last; x != null; x = x.prev) { //逆向向前 index--; if (x.item == null) return index; } } else { for (Node<E> x = last; x != null; x = x.prev) { index--; if (o.equals(x.item)) return index; } } return -1; }
9、clone克隆
//返回此 LinkedList实例的浅拷贝 public Object clone() { LinkedList<E> clone = superClone(); // Put clone into "virgin" state clone.first = clone.last = null; clone.size = 0; clone.modCount = 0; // Initialize clone with our elements for (Node<E> x = first; x != null; x = x.next) clone.add(x.item); return clone; }
相关文章推荐
- LinkedList源码解析(jdk1.8)
- Java之LinkedList源码解读(JDK 1.8)
- 【集合框架】JDK1.8源码分析之LinkedList(七)
- Java集合框架--LinkedList源码解析(JDK1.7)
- LinkedList源码分析(基于jdk1.8)
- LinkedList源码分析(jdk1.8)
- Java集合框架成员之LinkedList类的源码分析(基于JDK1.8版本)
- Java之LinkedList源码解读(JDK 1.8)
- Java -- 基于JDK1.8的LinkedList源码分析
- LinkedList源码解析 给jdk写注释系列之jdk1.6容器(2)
- LinkedList源码解析(基于JDK1.7)
- JDK之LinkedList源码解析
- 基于JDK1.8的LinkedList源码学习笔记
- 【集合框架】JDK1.8源码分析之LinkedList(七)
- 【源码解析】JDK源码之LinkedList
- JDK源码解析之LinkedList
- LinkedList 源码分析(JDK 1.8)
- java容器源码分析--LinkedList(JDK1.8)
- JDK源码解析之LinkedList
- Java集合源码实现二:LinkedList(jdk1.8)