对集合类的源码分析主要从一下几个方面进行:
/** *大小 */ transient int size = 0; /** * 头结点 */ transient Node<E> first; /** * 尾结点 */ transient Node<E> last;
从常量可以看出,LinkedList中的每个位置是节点Node,那就先看一下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; } }
/** * 构建一个空的LinkedList. */ public LinkedList() { } /** *构建一个以参数传入的值的LinkedList */ public LinkedList(Collection<? extends E> c) { this(); addAll(c); }
//向链表的头部添加元素 public void addFirst(E e) { //调用私有方法进行添加 linkFirst(e); } //向链表的头部添加元素 private void linkFirst(E e) { //定义一个元素存放原先的第一个元素 final Node<E> f = first; //用传进来的值创建一个Node,前一个节点为空,后一个节点就是原先的第一个节点 final Node<E> newNode = new Node<>(null, e, f); //新创建的节点为第一个节点 first = newNode; //如果原先的第一个节点为空,说明原先链表没有数据,插入进来的节点即是第一个节点,也是最后一个节点 if (f == null) last = newNode; else //如果不为空,原先第一个节点的前一个节点指向新创建的节点 f.prev = newNode; //大小加一 size++; //修改次数加一 modCount++; } //向链表的尾部添加元素 public void addLast(E e) { //调用私有方法进行添加 linkLast(e); } //向链表的尾部添加元素 void linkLast(E e) { //定义一个元素存放原先的最后一个元素 final Node<E> l = last; //用传进来的值创建一个Node,后节点为空,前节点为原先的最后一个节点 final Node<E> newNode = new Node<>(l, e, null); //把新创建的节点设置为最后一个节点 last = newNode; //如果原先的最后一个节点为空,说明原先链表没有数据,插入进来的节点即是第一个节点,也是最后一个节点 if (l == null) first = newNode; else //如果不为空,原先的最后一个节点的下一个节点指向新创建的节点 l.next = newNode; //大小加一 size++; //修改次数加一 modCount++; } //添加元素,向链表的尾部添加元素 public boolean add(E e) { linkLast(e); return true; } //添加元素,向链表的index位置添加元素 public void add(int index, E element) { //检查index的位置是否合法 checkPositionIndex(index); //如果index等于size说明就是向链表的尾部添加数据 if (index == size) //直接调用添加到尾部的方法 linkLast(element); else //调用添加到某个位置之前的方法 linkBefore(element, node(index)); } //在不为空的节点前添加元素 void linkBefore(E e, Node<E> succ) { // assert succ != null; //找到不为空的节点的前一个节点 final Node<E> pred = succ.prev; //用传进来的元素创建一个Node,pred为前节点,succ为后节点 final Node<E> newNode = new Node<>(pred, e, succ); //设置succ的前节点为newNode succ.prev = newNode; //如果前节点为空,说明插入的位置为第一个节点,所有把newNode设置为第一个节点 if (pred == null) first = newNode; else //如果不为空,设置前一个节点的下一个节点为newNode pred.next = newNode; //大小加一 size++; //修改次数加一 modCount++; } 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 { //从尾部开始遍历 Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } } //添加所有 public boolean addAll(int index, Collection<? extends E> c) { //检查下标是否越界 checkPositionIndex(index); //转为数组 Object[] a = c.toArray(); int numNew = a.length; //检查添加的集合是否为空 if (numNew == 0) return false; //pred插入的前一个节点 succ插入的后一个节点 Node<E> pred, succ; //index=size等于把值从链表的最后开始添加 if (index == size) { succ = null; pred = last; } else { //不等,找出index所在的前一位和index所在的位置的值 succ = node(index); pred = succ.prev; } for (Object o : a) { @SuppressWarnings("unchecked") E e = (E) o; //创建一个Node节点,设置pred为前一个节点 Node<E> newNode = new Node<>(pred, e, null); //如果前一个节点为空,说明LinkedList中没有值,设置newNode为第一个节点 if (pred == null) first = newNode; else //如果不为空,设置newNode为前一个节点的下一个节点 pred.next = newNode; //把前一个节点设置为newNode pred = newNode; } //如果index所在节点为空,说明是最后一个节点,设置pred为最后节点 if (succ == null) { last = pred; } else { //如果不为空,连上链表即可 //前一个节点的下一个节点为succ pred.next = succ; //将pred设置为succ的前一个节点 succ.prev = pred; } //大小增加 size += numNew; //修改次数增加 modCount++; return true; }
//移除指定节点 public boolean remove(Object o) { //如果传入的值是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; } //移除对应的节点 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; //大小减一 size--; //修改次数加一 modCount++; //返回旧值 return element; } //移除指定位置的值 public E remove(int index) { //检查下标是否越界 checkElementIndex(index); return unlink(node(index)); } //移除第一个元素,直接调用的是unlinkFirst方法 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; } //移除最后一个元素,直接调用的是unlinkLast方法 public E removeLast() { final Node<E> l = last; if (l == null) throw new NoSuchElementException(); return unlinkLast(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; //如果前一个节点为空,说明链表就一个字段,所以移除后,第一个节点为空 if (prev == null) first = null; else //如果不是,设置前一个节点也就是最后一个节点的下一个节点为空 prev.next = null; //大小减一 size--; //修改次数加一 modCount++; //返回移除的旧值 return element; }
public E set(int index, E element) { //检查下标是否正确 checkElementIndex(index); //对到index位置的节点 Node<E> x = node(index); //得到旧节点的值 E oldVal = x.item; //将新值设置到Node节点中 x.item = element; //返回旧值 return oldVal; }
//得到第一个节点的值 public E getFirst() { final Node<E> f = first; 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 get(int index) { //检查传入的值的有效性 checkElementIndex(index); //通过node方法,得到节点,最后得到对应节点的值 return node(index).item; }
//得到双向遍历的迭代器 public ListIterator<E> listIterator(int index) { //检查下标是否正确 checkPositionIndex(index); //创建迭代器 return new ListItr(index); } //双向迭代器 private class ListItr implements ListIterator<E> { //上一次返回的 private Node<E> lastReturned; //下一个节点 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() { return nextIndex < size; } //获取下一个节点的值 public E next() { //检查是否有并发修改过 checkForComodification(); //如果没有下一个,抛出异常 if (!hasNext()) throw new NoSuchElementException(); //把下一个,也就是当前的节点赋值给lastReturned lastReturned = next; //设置下一个节点 next = next.next; //下标加一 nextIndex++; //返回当前节点的值 return lastReturned.item; } //如果下一个节点的下标大于0,说明还有上一个节点 public boolean hasPrevious() { return nextIndex > 0; } public E previous() { //检查是否被并发修改了 checkForComodification(); //没有上一个节点,抛出异常 if (!hasPrevious()) throw new NoSuchElementException(); //设置上一个节点,如果next节点为空,说明在链表的尾部,所以就是last,如果不是,获取上一个节点 lastReturned = next = (next == null) ? last : next.prev; //下标减一 nextIndex--; return lastReturned.item; } public int nextIndex() { return nextIndex; } public int previousIndex() { return nextIndex - 1; } //移除元素 public void 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) { if (lastReturned == null) throw new IllegalStateException(); checkForComodification(); //修改节点中的值 lastReturned.item = e; } public void add(E e) { checkForComodification(); lastReturned = null; //如果下一个节点为空,说明已经到尾部了,添加到尾部即可 if (next == null) linkLast(e); else //如果不是添加到节点之前 linkBefore(e, next); nextIndex++; expectedModCount++; } public void forEachRemaining(Consumer<? super E> action) { Objects.requireNonNull(action); while (modCount == expectedModCount && nextIndex < size) { action.accept(next.item); lastReturned = next; next = next.next; nextIndex++; } checkForComodification(); } //检查是否有并发修改的情况 final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
//得到头结点的值,但不移除元素,为空返回null public E peek() { final Node<E> f = first; return (f == null) ? null : f.item; } //得到头结点的值,但不移除元素,和peek不一样的地方是如果为空抛出异常 public E element() { return getFirst(); } //得到头结点的值,并移除元素,为空返回null public E poll() { final Node<E> f = first; return (f == null) ? null : unlinkFirst(f); } //得到头结点的值,并移除元素,和poll不一样的地方是如果为空抛出异常 public E remove() { return removeFirst(); } //向链表尾部添加元素,其实内部就是调用add public boolean offer(E e) { return add(e); } //向链表头部添加元素,其实内部就是调用addFirst public boolean offerFirst(E e) { addFirst(e); return true; } //向链表尾部添加元素,和offer是一样的 public boolean offerLast(E e) { addLast(e); return true; } //得到链表的头部节点的值,但不移除元素 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() { final Node<E> f = first; return (f == null) ? null : unlinkFirst(f); } //弹出最后一个节点的值,并移除元素 public E pollLast() { final Node<E> l = last; return (l == null) ? null : unlinkLast(l); } //添加元素,内部就是调用添加到第一个 public void push(E e) { addFirst(e); } //弹出第一个元素并移除,为空抛出异常 public E pop() { return removeFirst(); }