一步一步解析集合框架LinkedList源码(4)
2016-07-30 10:38
453 查看
我在阅读源码的过程中很多时候是没有头绪的。所以为了避免大家也遇到这种状况,源码不求全求大,做到“透过实践看源码”,分块分层。
列出总体的部分源码
列出总体的部分源码
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 void linkFirst(E e) { final Node<E> f = first; //构造新节点,指定next节点是first final Node<E> newNode = new Node<>(null, e, f); first = newNode; //第一次添加数据,f==null;first和last均指向新节点 if (f == null) last = newNode; else f.prev = newNode;//成功构建双向节点,加入链表 size++; modCount++; } /** * 将元素e添加至链表末尾, * 双向的,类似于:first--->A---->B---->...--->last * <-- <--- <--- ...<-- */ void linkLast(E e) { //第一次添加数据,因为last并没有实例化,所以l不是指向last的引用,l=null final Node<E> l = last; //根据添加的元素创建一个节点,将last节点作为prev节点,next节点设置为空,随后设置 final Node<E> newNode = new Node<>(l, e, null); //将新构建的节点作为last节点,保证每次添加都添加至末尾 last = newNode; //第一次添加,将first指向newNode节点(新构建的) if (l == null) first = newNode; else l.next = newNode;//以后每次都将最后一个节点的next只想新节点 size++;//元素数递增 modCount++; } /** * 插入节点 * 在节点Node<E> 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); //重新进行双向链接 succ.prev = newNode; //在首节点处插入,pred==null if (pred == null) first = newNode; else pred.next = newNode; size++; modCount++; } /** * 返回删除的节点值 * 解除第一个节点的链接,即删除第一个元素 * f!=null */ private E unlinkFirst(Node<E> f) { //传递参数f之前就已经判断f!=null 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;//首节点的prev为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节点 last = prev; //链表只有一个数据, if (prev == null) first = null; else prev.next = null; size--; modCount++; return element;//返回值 } /** * 删除节点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; //如果删除的是第一个节点,prev=null 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; } /** * 返回链表第一个元素值 */ public E getFirst() { final Node<E> f = first; //未添加数据,f==null,抛出异常 if (f == null) throw new NoSuchElementException(); return f.item;//节点值 } /** * 返回最后一个节点值 */ public E getLast() { final Node<E> l = last; if (l == null) throw new NoSuchElementException(); return l.item;//节点值 } /** *删除第一个元素 */ public E removeFirst() { final Node<E> f = first; if (f == null) throw new NoSuchElementException(); return unlinkFirst(f); } /** * 删除最后一个元素 */ 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 */ public boolean contains(Object o) { return indexOf(o) != -1; } /** * 链表元素个数 */ public int size() { return size; } /** * 添加数据元素 */ public boolean add(E e) { linkLast(e); return true; } /** *根据值进行删除 */ 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中的元素全部添加进链表 */ public boolean addAll(Collection<? extends E> c) { return addAll(size, c); } /** *将集合c中的元素全部添加进链表 *addAll(Collection<? extends E> c)函数调用传递参数index==size *带参构造函数index==size==0 */ public boolean addAll(int index, Collection<? extends E> c) { checkPositionIndex(index); //将集合c转化成数组 Object[] a = c.toArray(); int numNew = a.length; if (numNew == 0) return false; Node<E> pred, succ; //index==size; if (index == size) { succ = null; pred = last; } else { succ = node(index); pred = succ.prev; } //遍历数组,每次添加至尾节点 for (Object o : a) { @SuppressWarnings("unchecked") E e = (E) o; //构造新节点,prev(前一节点)节点均是尾节点,第一次直接是last节点,以后每次是更新的尾节点 Node<E> newNode = new Node<>(pred, e, null); //pred==null,表明原链表没有数据 if (pred == null) first = newNode; else pred.next = newNode; pred = newNode;//将新构建的节点作为下个新节点的prev节点 } //succ==null if (succ == null) { last = pred; } else { pred.next = succ; succ.prev = pred; } size += numNew; modCount++; return true; } /** * 清空链表 */ public void clear() { //遍历,清空节点值,断开链接 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++; } // Positional Access Operations /** * 获取指定索引节点值 */ public E get(int index) { checkElementIndex(index); return node(index).item; } /** * 设置指定索引节点值 */ public E set(int index, E element) { checkElementIndex(index); Node<E> x = node(index); E oldVal = x.item; x.item = element; return oldVal; } /** * 通过索引添加元素 */ public void add(int index, E element) { checkPositionIndex(index); if (index == size) linkLast(element); else linkBefore(element, node(index)); } /** * 删除对应索引元素值 */ public E remove(int index) { checkElementIndex(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; } /** * Constructs an IndexOutOfBoundsException detail message. * Of the many possible refactorings of the error handling code, * this "outlining" performs best with both server and client VMs. */ private String outOfBoundsMsg(int index) { return "Index: "+index+", Size: "+size; } private void checkElementIndex(int index) { if (!isElementIndex(index)) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } //检查索引的合理性 private void checkPositionIndex(int index) { //索引超出范围,抛出异常 if (!isPositionIndex(index)) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /** * 返回对应索引index节点 */ Node<E> node(int index) { // assert isElementIndex(index); //size >> 1 表示size/2,通过这种比较可以更快的查找到节点 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; } } // Search Operations /** * 元素值的索引 */ public int indexOf(Object o) { int index = 0; //通过遍历链表元素,比较获取索引值,first元素对应索引为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++; } } //不存在就返回-1 return -1; } /** * 从尾节点遍历,获取对应元素的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; } /** * 返回首节点元素值 */ public E element() { return getFirst(); } /** * 删除首节点并返回 */ public E poll() { final Node<E> f = first; return (f == null) ? null : unlinkFirst(f); } /** * 删除首节点 */ public E remove() { return removeFirst(); } /** *添加数据 */ public boolean offer(E e) { return add(e); } // Deque operations /** * Inserts the specified element at the front of this list. * * @param e the element to insert * @return {@code true} (as specified by {@link Deque#offerFirst}) * @since 1.6 */ public boolean offerFirst(E e) { addFirst(e); return true; } /** * Inserts the specified element at the end of this list. * * @param e the element to insert * @return {@code true} (as specified by {@link Deque#offerLast}) * @since 1.6 */ public boolean offerLast(E e) { addLast(e); return true; } /** * Retrieves, but does not remove, the first element of this list, * or returns {@code null} if this list is empty. * * @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; } /** * 返回尾节点元素值 */ public E peekLast() { final Node<E> l = last; return (l == null) ? null : l.item; } /** * 弹出首节点 * 删除并返回 */ public E pollFirst() { //未添加数据,f==null final Node<E> f = first; return (f == null) ? null : unlinkFirst(f); } /** * 弹出尾节点 * 删除并返回 */ public E pollLast() { //未添加数据时l==null final Node<E> l = last; return (l == null) ? null : unlinkLast(l); } /** * 压入 * 在首节点处增加数据 */ public void push(E e) { addFirst(e); } /** * 弹出 * 删除并返回第一个元素值 */ public E pop() { return removeFirst(); } /** *删除第一个匹配的节点 */ public boolean removeFirstOccurrence(Object o) { return remove(o); } /** * */ 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; } }
相关文章推荐
- 2009 求数列的和
- MD5加密
- 栈之行编辑器
- 进程和线程
- vim基本命令
- 在centOS上安装Ubuntu字体
- 常用git命令
- 一张图看懂linux查找文件的过程
- 华为2016校园招聘上机笔试题
- LinearLayout布局下Button按钮不可见
- 关于magento后台编辑器
- (多校第四场1001)HDU5763 Another Meaning (DP、KMP)
- Android打印工具
- SQL注入--盲注入(time型)
- Java利用PropertyDescriptor获取属性的 getter/setter 方法
- 了凡四训
- IOS Dev Intro - UIView and CALayer
- cd dirname $0
- POJ 1572 Automatic Editing 字符串替换,replace就够了
- Lync 小技巧-54-Elastix IVR 转换Wav方法