/** * Constructs an empty list. */ publicLinkedList() { }
无参的构造方法实际上什么都没有做,返回的 LinkedList 对象中,size 为默认值 0,first 和 last 的值都是 null。
从集合初始化的构造方法
1 2 3 4 5 6 7 8 9 10 11 12
/** * Constructs a list containing the elements of the specified * collection, in the order they are returned by the collection's * iterator. * * @param c the collection whose elements are to be placed into this list * @throws NullPointerException if the specified collection is null */ publicLinkedList(Collection<? extends E> c) { this(); addAll(c); }
/** * Inserts the specified element at the beginning of this list. * * @param e the element to add */ publicvoidaddFirst(E e) { linkFirst(e); }
该方法又调用了一个 private 方法 linkFirst(E) 实现在头部插入数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/** * Links e as first element. */ privatevoidlinkFirst(E e) { final Node<E> f = first; final Node<E> newNode = newNode<>(null, e, f); first = newNode; if (f == null) last = newNode; else f.prev = newNode; size++; modCount++; }
根据链表的特性可以知道,如果一个链表不是空的,那么它的 first 必定非空;反之,如果它的 first 为 null,那么这个链表一定为空。所以根据这个规则,它会判断在插入元素前,这个链表是不是空的,如果是空的,那么新元素就同时作为链表的尾 last;如果不是空的,那么就让原来的 first 的 prev 指向新插入的元素。这样操作之后,新元素与原 first 元素之间就出现了一个双向的引用,即完成了一个小的双向链表。
/** * Appends the specified element to the end of this list. * * <p>This method is equivalent to {@link #add}. * * @param e the element to add */ publicvoidaddLast(E e) { linkLast(e); }
/** * Appends the specified element to the end of this list. * * <p>This method is equivalent to {@link #addLast}. * * @param e element to be appended to this list * @return {@code true} (as specified by {@link Collection#add}) */ publicbooleanadd(E e) { linkLast(e); returntrue; }
可以看出,两个方法都是通过一个 private 方法 linkLast(E) 实现的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/** * Links e as last element. */ voidlinkLast(E e) { final Node<E> l = last; final Node<E> newNode = newNode<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; }
在尾部插入数据的操作与在头部插入数据的操作类似,依旧是构造一个新的节点,使原来的 last 节点指向新节点,然后根据原链表是否为空执行后续操作。在这里就不多赘述了。
在中间增加节点
要在链表中间插入数据,可以使用 add(int, E) 方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/** * Inserts the specified element at the specified position in this list. * Shifts the element currently at that position (if any) and any * subsequent elements to the right (adds one to their indices). * * @param index index at which the specified element is to be inserted * @param element element to be inserted * @throws IndexOutOfBoundsException {@inheritDoc} */ publicvoidadd(int index, E element) { checkPositionIndex(index);
if (index == size) linkLast(element); else linkBefore(element, node(index)); }
privatevoidcheckPositionIndex(int index) { if (!isPositionIndex(index)) thrownewIndexOutOfBoundsException(outOfBoundsMsg(index)); }
/** * Tells if the argument is the index of a valid position for an * iterator or an add operation. */ privatebooleanisPositionIndex(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; }
/** * Returns the (non-null) Node at the specified element index. */ Node<E> node(int index) { // assert isElementIndex(index);
if (index < (size >> 1)) { Node<E> x = first; for (inti=0; i < index; i++) x = x.next; return x; } else { Node<E> x = last; for (inti= size - 1; i > index; i--) x = x.prev; return x; } }
/** * Inserts element e before non-null Node succ. */ voidlinkBefore(E e, Node<E> succ) { // assert succ != null; final Node<E> pred = succ.prev; final Node<E> newNode = newNode<>(pred, e, succ); succ.prev = newNode; if (pred == null) first = newNode; else pred.next = newNode; size++; modCount++; }
/** * Appends all of the elements in the specified collection to the end of * this list, in the order that they are returned by the specified * collection's iterator. The behavior of this operation is undefined if * the specified collection is modified while the operation is in * progress. (Note that this will occur if the specified collection is * this list, and it's nonempty.) * * @param c collection containing elements to be added to this list * @return {@code true} if this list changed as a result of the call * @throws NullPointerException if the specified collection is null */ publicbooleanaddAll(Collection<? extends E> c) { return addAll(size, c); }
/** * Inserts all of the elements in the specified collection into this * list, starting at the specified position. Shifts the element * currently at that position (if any) and any subsequent elements to * the right (increases their indices). The new elements will appear * in the list in the order that they are returned by the * specified collection's iterator. * * @param index index at which to insert the first element * from the specified collection * @param c collection containing elements to be added to this list * @return {@code true} if this list changed as a result of the call * @throws IndexOutOfBoundsException {@inheritDoc} * @throws NullPointerException if the specified collection is null */ publicbooleanaddAll(int index, Collection<? extends E> c) { checkPositionIndex(index);
Object[] a = c.toArray(); intnumNew= a.length; if (numNew == 0) returnfalse;
Node<E> pred, succ; if (index == size) { succ = null; pred = last; } else { succ = node(index); pred = succ.prev; }
for (Object o : a) { @SuppressWarnings("unchecked")Ee= (E) o; Node<E> newNode = newNode<>(pred, e, null); if (pred == null) first = newNode; else pred.next = newNode; pred = newNode; }
if (succ == null) { last = pred; } else { pred.next = succ; succ.prev = pred; }
/** * Returns the first element in this list. * * @return the first element in this list * @throws NoSuchElementException if this list is empty */ public E getFirst() { final Node<E> f = first; if (f == null) thrownewNoSuchElementException(); return f.item; }
/** * Retrieves, but does not remove, the head (first element) of this list. * * @return the head of this list, or {@code null} if this list is empty * @since 1.5 */ public E peek() { final Node<E> f = first; return (f == null) ? null : f.item; }
/** * Retrieves and removes the head (first element) of this list. * * @return the head of this list, or {@code null} if this list is empty * @since 1.5 */ public E poll() { final Node<E> f = first; return (f == null) ? null : unlinkFirst(f); }
/** * Returns the last element in this list. * * @return the last element in this list * @throws NoSuchElementException if this list is empty */ public E getLast() { final Node<E> l = last; if (l == null) thrownewNoSuchElementException(); return l.item; }
/** * Retrieves, but does not remove, the last element of this list, * or returns {@code null} if this list is empty. * * @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; }
/** * Retrieves and removes the last element of this list, * or returns {@code null} if this list is empty. * * @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); }
取出中间的节点
要从链表中的某个位置取出节点,可以使用 get(int) 方法。
1 2 3 4 5 6 7 8 9 10 11
/** * Returns the element at the specified position in this list. * * @param index index of the element to return * @return the element at the specified position in this list * @throws IndexOutOfBoundsException {@inheritDoc} */ public E get(int index) { checkElementIndex(index); return node(index).item; }
/** * Returns {@code true} if this list contains the specified element. * More formally, returns {@code true} if and only if this list contains * at least one element {@code e} such that * <tt>(o==null ? e==null : o.equals(e))</tt>. * * @param o element whose presence in this list is to be tested * @return {@code true} if this list contains the specified element */ publicbooleancontains(Object o) { return indexOf(o) != -1; }
/** * Returns the index of the first occurrence of the specified element * in this list, or -1 if this list does not contain the element. * More formally, returns the lowest index {@code i} such that * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, * or -1 if there is no such index. * * @param o element to search for * @return the index of the first occurrence of the specified element in * this list, or -1 if this list does not contain the element */ publicintindexOf(Object o) { intindex=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; }
/** * Replaces the element at the specified position in this list with the * specified element. * * @param index index of the element to replace * @param element element to be stored at the specified position * @return the element previously at the specified position * @throws IndexOutOfBoundsException {@inheritDoc} */ public E set(int index, E element) { checkElementIndex(index); Node<E> x = node(index); EoldVal= x.item; x.item = element; return oldVal; }
/** * Removes and returns the first element from this list. * * @return the first element from this list * @throws NoSuchElementException if this list is empty */ public E removeFirst() { final Node<E> f = first; if (f == null) thrownewNoSuchElementException(); return unlinkFirst(f); }
/** * Removes and returns the last element from this list. * * @return the last element from this list * @throws NoSuchElementException if this list is empty */ public E removeLast() { final Node<E> l = last; if (l == null) thrownewNoSuchElementException(); return unlinkLast(l); }
/** * Removes the element at the specified position in this list. Shifts any * subsequent elements to the left (subtracts one from their indices). * Returns the element that was removed from the list. * * @param index the index of the element to be removed * @return the element previously at the specified position * @throws IndexOutOfBoundsException {@inheritDoc} */ public E remove(int index) { checkElementIndex(index); return unlink(node(index)); }
/** * Removes the first occurrence of the specified element from this list, * if it is present. If this list does not contain the element, it is * unchanged. More formally, removes the element with the lowest index * {@code i} such that * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> * (if such an element exists). Returns {@code true} if this list * contained the specified element (or equivalently, if this list * changed as a result of the call). * * @param o element to be removed from this list, if present * @return {@code true} if this list contained the specified element */ publicbooleanremove(Object o) { if (o == null) { for (Node<E> x = first; x != null; x = x.next) { if (x.item == null) { unlink(x); returntrue; } } } else { for (Node<E> x = first; x != null; x = x.next) { if (o.equals(x.item)) { unlink(x); returntrue; } } } returnfalse; }
/** * Removes the first occurrence of the specified element in this * list (when traversing the list from head to tail). If the list * does not contain the element, it is unchanged. * * @param o element to be removed from this list, if present * @return {@code true} if the list contained the specified element * @since 1.6 */ publicbooleanremoveFirstOccurrence(Object o) { return remove(o); }
/** * Removes the last occurrence of the specified element in this * list (when traversing the list from head to tail). If the list * does not contain the element, it is unchanged. * * @param o element to be removed from this list, if present * @return {@code true} if the list contained the specified element * @since 1.6 */ publicbooleanremoveLastOccurrence(Object o) { if (o == null) { for (Node<E> x = last; x != null; x = x.prev) { if (x.item == null) { unlink(x); returntrue; } } } else { for (Node<E> x = last; x != null; x = x.prev) { if (o.equals(x.item)) { unlink(x); returntrue; } } } returnfalse; }
/** * Pushes an element onto the stack represented by this list. In other * words, inserts the element at the front of this list. * * <p>This method is equivalent to {@link #addFirst}. * * @param e the element to push * @since 1.6 */ publicvoidpush(E e) { addFirst(e); }
/** * Pops an element from the stack represented by this list. In other * words, removes and returns the first element of this list. * * <p>This method is equivalent to {@link #removeFirst()}. * * @return the element at the front of this list (which is the top * of the stack represented by this list) * @throws NoSuchElementException if this list is empty * @since 1.6 */ public E pop() { return removeFirst(); }