LinkedList源码解析
2016-07-15 20:30
519 查看
LinkedList特点
1.内部通过双向链表存储数据
2.插入、删除不需要移动元素,只需要修改指针
3.实现了队列、双端队列、栈
4.插入、删除操作比较多的时候,推荐使用
5.获取指定index位置的值效率低
所在包
继承AbstractSequentialList抽象类
实现List、Deque、Cloneable、java.io.Serializable
Deque是双端队列接口
内部节点定义方式
可以看出是双向链表,只有一个构造器,参数:前驱节点,当前节点值,后继节点,节点构造好后,其前驱和后继节点也构建好
三个重要参数:size,first,last
两个构造器
头插入节点
尾部插入节点
succ之前插入节点
删除第一个节点,并返回节点值
删除最后一个节点,并返回节点值
删除节点 x 并返回节点值
获取第一个节点值
获取最后一个节点值
删除第一个节点,并返回其值,可抛出异常
删除最后一个节点,并返回节点值,可抛出异常
头尾插入节点
是否包含元素 o
获取元素的个数
尾部加入节点
删除节点 o
集合c中元素插入到LinkedList中
index开始 集合c中元素加入的LinkedList中
清空
获取index位置的元素
index位置元素的值更新
index位置插入新节点
删除index位置的节点
下标合法性的方法
返回index位置的节点
通过前后分开查找的方式
平均查找次数应该是:n/2
获取节点o第一次出现的下标
获取节点o最后一次出现的下标
队列的相关操作
双端队列相关操作
栈的相关操作
删除元素 o,只删除第一次出现的那个
删除元素o,删除最后一次出现的那个
返回从index开始的迭代器
后向前的迭代器
获取LinkedList的clone
转换成数组
LinkedList元素值更新数组a
序列号
输入输出流
1.内部通过双向链表存储数据
2.插入、删除不需要移动元素,只需要修改指针
3.实现了队列、双端队列、栈
4.插入、删除操作比较多的时候,推荐使用
5.获取指定index位置的值效率低
所在包
package java.util;
继承AbstractSequentialList抽象类
实现List、Deque、Cloneable、java.io.Serializable
Deque是双端队列接口
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable
内部节点定义方式
可以看出是双向链表,只有一个构造器,参数:前驱节点,当前节点值,后继节点,节点构造好后,其前驱和后继节点也构建好
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;// 前驱节点 } }
三个重要参数:size,first,last
// 元素个数 transient int size = 0; /** * 第一个节点 * Invariant: (first == null && last == null) || * (first.prev == null && first.item != null) */ transient Node<E> first; /** * 最后一个节点 * Invariant: (first == null && last == null) || * (last.next == null && last.item != null) */ transient Node<E> last;
两个构造器
/** * 空构造器 */ public LinkedList() { } /** * 集合c中元素加入的LinkedList中 * @param c the collection whose elements are to be placed into this list * @throws NullPointerException if the specified collection is null */ public LinkedList(Collection<? extends E> c) { this(); addAll(c); }
头插入节点
/** * 插入节点e作为第一个节点 */ private void linkFirst(E e) { final Node<E> f = first; final Node<E> newNode = new Node<>(null, e, f); // f 前插入 值为e的节点 first = newNode; // first指针指向当前新的节点 if (f == null) // f 为空所有没有元素,则last指向当前新的节点 last = newNode; else f.prev = newNode; // 建立f节点的前驱节点 size++;// 个数+1 modCount++; }
尾部插入节点
/** * 插入节点e作为最后一个节点 */ void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); // l 后 插入节点值为 e的节点 last = newNode;// last指针指向当前新的最后节点 if (l == null) // null 说明没有元素,first指向当前新的节点 first = newNode; else l.next = newNode;// 建立l 的后继节点 size++; modCount++; }
succ之前插入节点
/** * succ 前插入节点 */ void linkBefore(E e, Node<E> succ) { // assert succ != null; final Node<E> pred = succ.prev; final Node<E> newNode = new Node<>(pred, e, succ); // 新建节点 newNode.next = succ newNode.prev = pred succ.prev = newNode; // 建立前驱 if (pred == null) // 空时候 first = newNode; else // 建立后继 pred.next = newNode; size++; modCount++; }
删除第一个节点,并返回节点值
/** * 删除第一个节点,并返回节点值 */ 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; // 垃圾回收 first = next; // 更新first if (next == null) // 空 last = null; else next.prev = null; // 前驱为null size--; modCount++; return element; }
删除最后一个节点,并返回节点值
/** * 删除最后一个节点,并返回节点值 */ 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; // 垃圾回收 last = prev; // 更新last if (prev == null) // null first = null; else // 后继为null prev.next = null; size--; modCount++; return element; }
删除节点 x 并返回节点值
/** * 删除节点 x 并返回节点值 */ E unlink(Node<E> x) { // assert x != null; final E element = x.item; final Node<E> next = x.next;// next final Node<E> prev = x.prev; // prev if (prev == null) { // prev == null ,first = next first = next; } else { // prev.next = next prev.next = next; x.prev = null; // 垃圾回收 } if (next == null) { // next== null ,last = prev last = prev; } else { // next.prev = prev next.prev = prev; x.next = null; // for GC } x.item = null; // for GC size--; modCount++; return element; }
获取第一个节点值
/* @throws NoSuchElementException if this list is empty */ public E getFirst() { final Node<E> f = first; if (f == null) throw new NoSuchElementException(); return f.item; }
获取最后一个节点值
/** * 获取最后一个节点值 * @throws NoSuchElementException if this list is empty */ public E getLast() { final Node<E> l = last; if (l == null) throw new NoSuchElementException(); return l.item; }
删除第一个节点,并返回其值,可抛出异常
/** * 删除第一个节点,并返回其值,可抛出异常 * @throws NoSuchElementException if this list is empty */ public E removeFirst() { final Node<E> f = first; if (f == null) throw new NoSuchElementException(); return unlinkFirst(f); }
删除最后一个节点,并返回节点值,可抛出异常
/** * 删除最后一个节点,并返回节点值,可抛出异常 * @throws NoSuchElementException if this list is empty */ public E removeLast() { final Node<E> l = last; if (l == null) throw new NoSuchElementException(); return unlinkLast(l); }
头尾插入节点
/** * 第一个位置插入节点 */ public void addFirst(E e) { linkFirst(e); } /** * 最后一个位置插入节点 */ public void addLast(E e) { linkLast(e); }
是否包含元素 o
/** * 是否包含元素 o */ public boolean contains(Object o) { return indexOf(o) != -1; }
获取元素的个数
/** * 获取元素的个数 */ public int size() { return size; }
尾部加入节点
/** * 尾部加入节点 */ public boolean add(E e) { linkLast(e); return true; }
删除节点 o
/** * 删除节点 o * 顺序遍历查找,找到后删除 */ 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; }
集合c中元素插入到LinkedList中
/** * 集合c中元素加入的LinkedList中 * @throws NullPointerException if the specified collection is null */ public boolean addAll(Collection<? extends E> c) { return addAll(size, c); }
index开始 集合c中元素加入的LinkedList中
/** * index开始 集合c中元素加入的LinkedList中 * @throws IndexOutOfBoundsException {@inheritDoc} * @throws NullPointerException if the specified collection is null */ public boolean addAll(int index, Collection<? extends E> c) { checkPositionIndex(index); // 检查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);// 新节点 e.prev = pred e.next = 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; }
清空
/** * 清空 */ 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++; }
获取index位置的元素
/** * 获取index位置的元素 * @throws IndexOutOfBoundsException {@inheritDoc} */ public E get(int index) { checkElementIndex(index);// index合法性检查 return node(index).item; }
index位置元素的值更新
/** * index位置元素的值更新 * @throws IndexOutOfBoundsException {@inheritDoc} */ public E set(int index, E element) { checkElementIndex(index); // index合法性检查 Node<E> x = node(index); E oldVal = x.item; x.item = element; return oldVal; }
index位置插入新节点
/** * index位置插入新节点 * @throws IndexOutOfBoundsException {@inheritDoc} */ public void add(int index, E element) { checkPositionIndex(index); if (index == size) linkLast(element); else linkBefore(element, node(index)); }
删除index位置的节点
/** * 删除index位置的节点 * @throws IndexOutOfBoundsException {@inheritDoc} */ public E remove(int index) { checkElementIndex(index);// index合法性检查 return unlink(node(index)); }
下标合法性的方法
/** * 是不是下标 */ private boolean isElementIndex(int index) { return index >= 0 && index < size; } /** * 是否是合法的插入位置,插入可以查在最后一个节点的后面 */ private boolean isPositionIndex(int index) { return index >= 0 && index <= size; } /** * 越界输出信息 */ private String outOfBoundsMsg(int index) { return "Index: "+index+", Size: "+size; } /** * 检查index是否合法位置 */ private void checkElementIndex(int index) { if (!isElementIndex(index)) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /** * 检查index是否是合法的插入位置 */ private void checkPositionIndex(int index) { if (!isPositionIndex(index)) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
返回index位置的节点
通过前后分开查找的方式
平均查找次数应该是:n/2
/** * 返回index位置的节点 */ Node<E> node(int index) { // assert isElementIndex(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; } }
获取节点o第一次出现的下标
/** * 获取节点o第一次出现的下标 */ public int indexOf(Object o) { int index = 0; 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; }
获取节点o最后一次出现的下标
/** * 获取节点o最后一次出现的下标 */ public int lastIndexOf(Object o) { int index = size; 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; }
队列的相关操作
/** * 查看队顶元素 */ public E peek() { final Node<E> f = first; return (f == null) ? null : f.item; } /** * 查看队顶元素 * @throws NoSuchElementException if this list is empty * @since 1.5 */ public E element() { return getFirst(); } /** * 获取队顶元素,并删除该元素 * @since 1.5 */ public E poll() { final Node<E> f = first; return (f == null) ? null : unlinkFirst(f); } /** * 删除队顶元素,并返回该值 * @throws NoSuchElementException if this list is empty * @since 1.5 */ public E remove() { return removeFirst(); } /** * 队尾部加入元素 * @since 1.5 */ public boolean offer(E e) { return add(e); }
双端队列相关操作
/** * 第一个位置插入节点 * @since 1.6 */ public boolean offerFirst(E e) { addFirst(e); return true; } /** * 最后一个位置插入节点 * @since 1.6 */ public boolean offerLast(E e) { addLast(e); return true; } /** * 查看队顶元素 * * @return the first element of this list, or {@code null} * if this list is empty * @since 1.6 */ public E peekFirst() { final Node<E> f = first; return (f == null) ? null : f.item; } /** * 查看队尾元素 * @return the last element of this list, or {@code null} * if this list is empty * @since 1.6 */ public E peekLast() { final Node<E> l = last; return (l == null) ? null : l.item; } /** *队顶元素出队列 * @return the first element of this list, or {@code null} if * this list is empty * @since 1.6 */ public E pollFirst() { final Node<E> f = first; return (f == null) ? null : unlinkFirst(f); } /** * 队尾元素出队列 * @return the last element of this list, or {@code null} if * this list is empty * @since 1.6 */ public E pollLast() { final Node<E> l = last; return (l == null) ? null : unlinkLast(l); }
栈的相关操作
/** * 入栈 * @param e the element to push * @since 1.6 */ public void push(E e) { addFirst(e); } /** * 出栈 * @throws NoSuchElementException if this list is empty * @since 1.6 */ public E pop() { return removeFirst(); }
删除元素 o,只删除第一次出现的那个
/** * 删除元素 o,只删除第一次出现的那个 * @since 1.6 */ public boolean removeFirstOccurrence(Object o) { return remove(o); }
删除元素o,删除最后一次出现的那个
/** *删除元素o,删除最后一次出现的那个 * @since 1.6 */ 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; }
返回从index开始的迭代器
/** * 返回从index开始的迭代器 * @throws IndexOutOfBoundsException {@inheritDoc} * @see List#listIterator(int) */ public ListIterator<E> listIterator(int index) { checkPositionIndex(index);// 下标检查 return new ListItr(index); } private class ListItr implements ListIterator<E> { private Node<E> lastReturned = null; private Node<E> next; private int nextIndex; private int expectedModCount = modCount; ListItr(int index) { // assert isPositionIndex(index); next = (index == size) ? null : node(index); nextIndex = index; } public boolean hasNext() { // hasNext return nextIndex < size; } public E next() { // next checkForComodification(); if (!hasNext()) throw new NoSuchElementException(); lastReturned = next; next = next.next; nextIndex++; return lastReturned.item; } public boolean hasPrevious() { // hasPrevious return nextIndex > 0; } public E previous() { // previous checkForComodification(); if (!hasPrevious()) throw new NoSuchElementException(); lastReturned = next = (next == null) ? last : next.prev; nextIndex--; return lastReturned.item; } public int nextIndex() { // nextIndex return nextIndex; } public int previousIndex() { //previousIndex return nextIndex - 1; } public void remove() { // remove checkForComodification(); if (lastReturned == null) throw new IllegalStateException(); Node<E> lastNext = lastReturned.next; unlink(lastReturned); if (next == lastReturned) next = lastNext; else nextIndex--; lastReturned = null; expectedModCount++; } public void set(E e) { //set if (lastReturned == null) throw new IllegalStateException(); checkForComodification(); lastReturned.item = e; } public void add(E e) { // add checkForComodification(); lastReturned = null; if (next == null) linkLast(e); else linkBefore(e, next); nextIndex++; expectedModCount++; } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
后向前的迭代器
/** *后向前的迭代器 * @since 1.6 */ public Iterator<E> descendingIterator() { return new DescendingIterator(); } /** * 后向前的迭代器 */ private class DescendingIterator implements Iterator<E> { private final ListItr itr = new ListItr(size()); public boolean hasNext() { // 前驱 return itr.hasPrevious(); } public E next() { return itr.previous(); } public void remove() { itr.remove(); } }
获取LinkedList的clone
@SuppressWarnings("unchecked") private LinkedList<E> superClone() { try { return (LinkedList<E>) super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(); } } /** * 获取的一个clone * * @return a shallow copy of this {@code LinkedList} instance */ 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; }
转换成数组
public Object[] toArray() { Object[] result = new Object[size]; int i = 0; for (Node<E> x = first; x != null; x = x.next) result[i++] = x.item; return result; }
LinkedList元素值更新数组a
/** * @throws ArrayStoreException if the runtime type of the specified array * is not a supertype of the runtime type of every element in * this list * @throws NullPointerException if the specified array is null */ @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { if (a.length < size) a = (T[])java.lang.reflect.Array.newInstance( a.getClass().getComponentType(), size); int i = 0; Object[] result = a; for (Node<E> x = first; x != null; x = x.next) result[i++] = x.item; if (a.length > size) a[size] = null; return a; }
序列号
private static final long serialVersionUID = 876323262645176354L;
输入输出流
/** * Saves the state of this {@code LinkedList} instance to a stream * (that is, serializes it). * * @serialData The size of the list (the number of elements it * contains) is emitted (int), followed by all of its * elements (each an Object) in the proper order. */ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { // Write out any hidden serialization magic s.defaultWriteObject(); // Write out size s.writeInt(size); // Write out all elements in the proper order. for (Node<E> x = first; x != null; x = x.next) s.writeObject(x.item); } /** * Reconstitutes this {@code LinkedList} instance from a stream * (that is, deserializes it). */ @SuppressWarnings("unchecked") private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { // Read in any hidden serialization magic s.defaultReadObject(); // Read in size int size = s.readInt(); // Read in all elements in the proper order. for (int i = 0; i < size; i++) linkLast((E)s.readObject()); }
相关文章推荐
- 为什么说JavaScript中的DOM操作很慢
- Web安全之:WebShell的获取与查杀
- 华为OJ——计算字符串的距离
- Linux 服务器上建立用户并分配权限
- jzoj 1576. 【普及模拟】自动统计机 解题报告
- 【前端开发】HTML标签总结-行标签和块标签
- 字符串常量放在只读存储区
- 调用http://apistore.baidu.com网站的接口
- 【研发经验谈】模块间建链失败问题的分析及解决
- 带你一分钟理解 JavaScript 闭包
- pat L1-006. 连续因子
- 简单粗暴地理解 JavaScript 原型链
- 华为OJ——输出单向链表中倒数第k个结点
- 【AD】AD域环境下利用Supercrypt实现普通用户安装/运行/更新的方法
- 3689
- JavaScript 的 Date 最详细解读
- Android Studio 运行、编译卡死的解决办法
- 华为OJ——四则运算
- 数据库索引的创建 和 注意事项
- 12个非常实用的JavaScript小技巧