public class LinkedList<E>extends AbstractSequentialList<E>implements List<E>, Deque<E>, Cloneable, java.io.Serializable
LinkedList继承自AbstractSequenceList、实现了List及Deque接口。
AbstractSequenceList提供List接口的骨干实现,以减少实现List接口的复杂度。
Deque是Queue的一个子接口,双向队列是指该队列两端的元素既能入队(offer)也能出队(poll)。
- LinkedList的属性
transient int size = 0; //存储元素的个数
transient Node<E> first; //头节点 //jdk1.6 Entry<E> header = new Entry<E>(null, null, null);
transient Node<E> last; //尾节点 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() { //jdk1.6 header.next = header.previous = header;带有头结点双向循环链表} //jkd1.7+ 不带头节点的双向链表public LinkedList(Collection<? extends E> c) {this();addAll(c); //conllection 转换成数组 for循环添加}
- LinkedList的方法
add方法
public boolean add(E e) {linkLast(e); //直接添加到尾部return true;}public void add(int index, E element) {checkPositionIndex(index); //检查下标if (index == size)linkLast(element); //是在尾部添加else //中间插入linkBefore(element, node(index)); //查找index处的节点,把新节点添加到它的前面}private void checkPositionIndex(int index) {if (!isPositionIndex(index)) //非真就抛异常throw new IndexOutOfBoundsException(outOfBoundsMsg(index));}private boolean isPositionIndex(int index) {return index >= 0 && index <= size; //当于等于0且小于等于当前size的大小}void linkLast(E e) { //分2种情况解释 第一次添加 非第一次添加final Node<E> l = last; //第一次添加last为null 第二次添加last不是null final Node<E> newNode = new Node<>(l, e, null); //假如第一次添加个String类型的“1” 第二次添加个String类型的“2”last = newNode; //newNode的item是“1”,newNode.next=null newNode的item是“2”,newNode.next=null if (l == null) //nowNode.prev=null,并将成员变量last指向newNode nowNode.prev="1"first = newNode; //因为是第一次添加,l也是null, 第二次添加,l不是nullelse //将成员变量frist指向newNode 将当前添加的节点指向上一个节点的next属性l.next = newNode; //添加后是[null]["1"][null] [null]["1"]["2"][null]size++; // prve item next prve item nextmodCount++;}void linkBefore(E e, Node<E> succ) {// assert succ != null;final Node<E> pred = succ.prev; //获取succ前面的一个节点final Node<E> newNode = new Node<>(pred, e, succ); //新建一个节点,前面指向succ前面一个借点,后面指向succsucc.prev = newNode; //succ前面的节点指向新建的节点if (pred == null) //如果succ前面的节点为空,新建的节点则为头节点first = newNode;elsepred.next = newNode; //否则就将前面节点的下一点指向新建的节点size++;modCount++;}
remove方法
public boolean remove(Object o) { //判断要删除的元素是不是nullif (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 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) {// assert isElementIndex(index);if (index < (size >> 1)) { //假如index小于size的一半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) {// assert x != null; //假如LinkerList有这么一组数据[1,2,3,4,5] remove index是0的数据final E element = x.item; //则节点是1 x.item = 1 next = 2 prev = 3 final Node<E> next = x.next;final Node<E> prev = x.prev;if (prev == null) { //prev ==null,2现在就是首节点了first = next; //这里要注意一点,假如有这么一组数据[1,2,3,null,null,null,8,9],remove index是4} else { //item prve next 分别为空 ,只是表示指向的内容是nullprev.next = next; //假如删除的不是头结点,将下个节点指向上个节点的下个节点x.prev = null; //将删除的节点的上个节点指向设置为null}if (next == null) { last = prev;} else { //接着[1,2,3,4,5]来解释next.prev = prev; //假如删除的不是尾结点,prve此时是null了,2是首节点,2.prev = null;x.next = null; //将删除的节点的下个节点指向设置为null}x.item = null; //将删除的节点也置为nullsize--;modCount++;return element;}
set
public E set(int index, E element) {checkElementIndex(index); //检查数据下标越界Node<E> x = node(index); //获取要修改坐标的元素E oldVal = x.item; //获取这个坐标元素的item属性x.item = element; //将要修改元素的item属性引用指向elementreturn oldVal;}
get
public E get(int index) {checkElementIndex(index); //检查数据下标越界return node(index).item; //for循环来取}
Iterator
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) {next = (index == size) ? null : node(index);nextIndex = index;}public boolean hasNext() {return nextIndex < size;}public E next() {checkForComodification();if (!hasNext())throw new NoSuchElementException();lastReturned = next;next = next.next;nextIndex++;return lastReturned.item;}public boolean hasPrevious() {return nextIndex > 0;}public E previous() {checkForComodification();if (!hasPrevious())throw new NoSuchElementException();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;elsenextIndex--;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);elselinkBefore(e, next);nextIndex++;expectedModCount++;}final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}}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基于双向链表实现,有序,允许为null,没有固定容量,不需要扩容。
其中的每个对象包含数据的同时还包含指向链表中前一个与后一个元素的引用。