Java集合(三)-LinkedList
阿新 • • 發佈:2019-02-15
LinkedList原始碼分析(JDk6)
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable { //連結串列的表頭,表頭不含有任何資料 private transient Entry<E> header = new Entry<E>(null, null, null); //linkedList的元素個數 private transient int size = 0; //建立一個空的Linkedlist public LinkedList() { header.next = header.previous = header; } //建立一個包含集合的LinkedList public LinkedList(Collection<? extends E> c) { this(); addAll(c); } //返回連結串列的第一個元素,為空丟擲異常 public E getFirst() { if (size==0) throw new NoSuchElementException(); return header.next.element; } //返回連結串列的最後一個元素,為空丟擲異常 public E getLast() { if (size==0) throw new NoSuchElementException(); return header.previous.element; } //刪除連結串列第一個元素,並且返回刪除元素 public E removeFirst() { return remove(header.next); } //刪除連結串列的最後一個元素,並返回刪除元素 public E removeLast() { return remove(header.previous); } //將元素新增的連結串列的起始位置 public void addFirst(E e) { addBefore(e, header.next); } //將元素新增到連結串列的最後 public void addLast(E e) { addBefore(e, header); } //是否包含某個元素 public boolean contains(Object o) { return indexOf(o) != -1; } //返回LinkedList的大小 public int size() { return size; } //將元素新增到LinkedList中,新增到雙向連結串列的末端 public boolean add(E e) { addBefore(e, header); return true; } //從LinkedList中刪除某個元素,先判斷元素是否為null,都是從連結串列頭開始查詢,並刪除元素,返回true public boolean remove(Object o) { if (o==null) { for (Entry<E> e = header.next; e != header; e = e.next) { if (e.element==null) { remove(e); return true; } } } else { for (Entry<E> e = header.next; e != header; e = e.next) { if (o.equals(e.element)) { remove(e); return true; } } } return false; } //將集合新增到雙向連結串列的末端 public boolean addAll(Collection<? extends E> c) { return addAll(size, c); } //從雙向連結串列的index開始,將集合新增的連結串列中(1.邊界判定 2.新增元素) public boolean addAll(int index, Collection<? extends E> c) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("Index: "+index+ ", Size: "+size); Object[] a = c.toArray(); int numNew = a.length; if (numNew==0) return false; modCount++; //設定當前要插入節點的後一節點 Entry<E> successor = (index==size ? header : entry(index)); //設定當前要插入節點的前一節點 Entry<E> predecessor = successor.previous; //將集合新增到雙向連結串列中 for (int i=0; i<numNew; i++) { Entry<E> e = new Entry<E>((E)a[i], successor, predecessor); predecessor.next = e; predecessor = e; } successor.previous = predecessor; size += numNew; return true; } //清除雙向連結串列,從連結串列頭開始。 public void clear() { Entry<E> e = header.next; while (e != header) { Entry<E> next = e.next; e.next = e.previous = null; e.element = null; e = next; } header.next = header.previous = header; size = 0; modCount++; } //返回index位置對應的節點元素 public E get(int index) { return entry(index).element; } //設定index位置的元素值為element,並返回原值 public E set(int index, E element) { Entry<E> e = entry(index); E oldVal = e.element; e.element = element; return oldVal; } //在index前新增節點,並且節點的值為element public void add(int index, E element) { addBefore(element, (index==size ? header : entry(index))); } //刪除Index位置是元素,並返回 public E remove(int index) { return remove(entry(index)); } //獲取雙向連結串列中index位置的節點(1.邊界判定 2.二分查詢) private Entry<E> entry(int index) { if (index < 0 || index >= size) throw new IndexOutOfBoundsException("Index: "+index+ ", Size: "+size); Entry<E> e = header; if (index < (size >> 1)) { for (int i = 0; i <= index; i++) e = e.next; } else { for (int i = size; i > index; i--) e = e.previous; } return e; } //從前往後查詢返回值物件o對應的位置索引 public int indexOf(Object o) { int index = 0; if (o==null) { for (Entry e = header.next; e != header; e = e.next) { if (e.element==null) return index; index++; } } else { for (Entry e = header.next; e != header; e = e.next) { if (o.equals(e.element)) return index; index++; } } return -1; } //從後往前查詢值物件o對應的位置索引 public int lastIndexOf(Object o) { int index = size; if (o==null) { for (Entry e = header.previous; e != header; e = e.previous) { index--; if (e.element==null) return index; } } else { for (Entry e = header.previous; e != header; e = e.previous) { index--; if (o.equals(e.element)) return index; } } return -1; } //返回第一個節點,如果LinkedList的大小為0,則返回Null public E peek() { if (size==0) return null; return getFirst(); } //返回第一個節點,如果LinkedList的大小為0,則丟擲異常 public E element() { return getFirst(); } //刪除並返回第一個節點,如果大小為0,則返回Null public E poll() { if (size==0) return null; return removeFirst(); } //刪除並返回第一個節點,如果大小為0,丟擲異常 public E remove() { return removeFirst(); } //將e新增到雙向連結串列尾部 public boolean offer(E e) { return add(e); } //將e新增到雙向連結串列頭部 public boolean offerFirst(E e) { addFirst(e); return true; } //將E新增到雙向連結串列頭部 public boolean offerLast(E e) { addLast(e); return true; } //返回第一個節點,大小為0,返回Null public E peekFirst() { if (size==0) return null; return getFirst(); } //返回最後一個節點,大小為0,返回Null public E peekLast() { if (size==0) return null; return getLast(); } //刪除並返回第一個節點,大小為0,返回Null public E pollFirst() { if (size==0) return null; return removeFirst(); } //刪除並返回最後一個節點,大小為0,返回Null public E pollLast() { if (size==0) return null; return removeLast(); } //將e新增到第一個節點 public void push(E e) { addFirst(e); } //刪除並返回第一個節點 public E pop() { return removeFirst(); } //從linkedList頭往後查詢,刪除第一個值為o的元素的節點 public boolean removeFirstOccurrence(Object o) { return remove(o); } public boolean removeLastOccurrence(Object o) { if (o==null) { for (Entry<E> e = header.previous; e != header; e = e.previous) { if (e.element==null) { remove(e); return true; } } } else { for (Entry<E> e = header.previous; e != header; e = e.previous) { if (o.equals(e.element)) { remove(e); return true; } } } return false; } //返回index到尾部的全部節點對應的ListIterator物件 public ListIterator<E> listIterator(int index) { return new ListItr(index); } //list迭代器 private class ListItr implements ListIterator<E> { private Entry<E> lastReturned = header; //上一次返回的節點 private Entry<E> next;//下一個節點 private int nextIndex;//下一個節點對應的索引值 private int expectedModCount = modCount;//期望的改變計數 //建構函式,從in ListItr(int index) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("Index: "+index+ ", Size: "+size); if (index < (size >> 1)) { next = header.next; for (nextIndex=0; nextIndex<index; nextIndex++) next = next.next; } else { next = header; for (nextIndex=size; nextIndex>index; nextIndex--) next = next.previous; } } //是否存在下一個元素 public boolean hasNext() { return nextIndex != size; } //獲取下一個元素 public E next() { checkForComodification(); if (nextIndex == size) throw new NoSuchElementException(); lastReturned = next; next = next.next; nextIndex++; return lastReturned.element; } //是否存在上一個元素 public boolean hasPrevious() { return nextIndex != 0; } //獲取上一個元素 public E previous() { if (nextIndex == 0) throw new NoSuchElementException(); lastReturned = next = next.previous; nextIndex--; checkForComodification(); return lastReturned.element; } //獲取下一位置索引 public int nextIndex() { return nextIndex; } //獲取上一位置索引 public int previousIndex() { return nextIndex-1; } //刪除雙向連結串列的當前節點 public void remove() { checkForComodification(); Entry<E> lastNext = lastReturned.next; try { LinkedList.this.remove(lastReturned); } catch (NoSuchElementException e) { throw new IllegalStateException(); } if (next==lastReturned) next = lastNext; else nextIndex--; lastReturned = header; expectedModCount++; } //設定當前節點為E public void set(E e) { if (lastReturned == header) throw new IllegalStateException(); checkForComodification(); lastReturned.element = e; } //將e新增到當前節點前面 public void add(E e) { checkForComodification(); lastReturned = header; addBefore(e, next); nextIndex++; expectedModCount++; } // 判斷 “modCount和expectedModCount是否相等”,依次來實現fail-fast機制。 final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } } // 雙向連結串列的節點所對應的資料結構。 // 包含3部分:上一節點,下一節點,當前節點值。 private static class Entry<E> { E element; Entry<E> next; Entry<E> previous; Entry(E element, Entry<E> next, Entry<E> previous) { this.element = element; this.next = next; this.previous = previous; } } private Entry<E> addBefore(E e, Entry<E> entry) { Entry<E> newEntry = new Entry<E>(e, entry, entry.previous); newEntry.previous.next = newEntry; newEntry.next.previous = newEntry; size++; modCount++; return newEntry; } private E remove(Entry<E> e) { if (e == header) throw new NoSuchElementException(); E result = e.element; e.previous.next = e.next; e.next.previous = e.previous; e.next = e.previous = null; e.element = null; size--; modCount++; return result; } // 反向迭代器 public Iterator<E> descendingIterator() { return new DescendingIterator(); } // 反向迭代器實現類。 private class DescendingIterator implements Iterator { final ListItr itr = new ListItr(size()); public boolean hasNext() { return itr.hasPrevious(); } public E next() { return itr.previous(); } public void remove() { itr.remove(); } } //克隆函式,返回LinkedList的克隆物件 public Object clone() { LinkedList<E> clone = null; try { clone = (LinkedList<E>) super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(); } // Put clone into "virgin" state clone.header = new Entry<E>(null, null, null); clone.header.next = clone.header.previous = clone.header; clone.size = 0; clone.modCount = 0; // Initialize clone with our elements for (Entry<E> e = header.next; e != header; e = e.next) clone.add(e.element); return clone; } // 返回LinkedList的Object[]陣列 public Object[] toArray() { Object[] result = new Object[size]; int i = 0; for (Entry<E> e = header.next; e != header; e = e.next) result[i++] = e.element; return result; } 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 (Entry<E> e = header.next; e != header; e = e.next) result[i++] = e.element; if (a.length > size) a[size] = null; return a; } private static final long serialVersionUID = 876323262645176354L; private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { s.defaultWriteObject(); // Write out size s.writeInt(size); // Write out all elements in the proper order. for (Entry e = header.next; e != header; e = e.next) s.writeObject(e.element); } private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); // Read in size int size = s.readInt(); // Initialize header header = new Entry<E>(null, null, null); header.next = header.previous = header; // Read in all elements in the proper order. for (int i=0; i<size; i++) addBefore((E)s.readObject(), header); } }
注意:對比過jdk6和jdk8的原始碼,對於linkedList的改變不是很多,重要的方法基本一致,屬性有改動,jdk6只是在Entryheader操作,而jdk8我認為為了便於操作和區分,引入node(first和last)這個node的本質和Entry是一樣的,都包括前一節點,後一節點,節點值。
LinkedList不存在容量不足的問題,同時它實現了serializable介面,當寫入到輸出流時,先寫入容量,在寫入每一個節點的值;當讀出輸出流先讀取容量,在讀取每一個元素
(3)LinkedList遍歷方式
1)通過迭代器(Iterator)遍歷
for(Iterator iter = list.iterator(); iter.hasNext();) iter.next();
2)通過快速隨機訪問這個其實我感覺就是for迴圈,那麼就不解釋增強for了
int size = list.size();
for (int i=0; i<size; i++) {
list.get(i);
}
3)通過pollFirst/pollLast遍歷:
while(list.pollFirst() != null);
while(list.pollLast() != null);
4)通過removeFirst/removeLast遍歷:
try { while(list.removeFirst() != null) ; } catch (NoSuchElementException e) { } try { while(list.removeLast() != null) ; } catch (NoSuchElementException e) { }
通過removeFirst/removeLast效率最高,但是會刪除元素資料,如果只是單獨的讀取不刪除資料,可以使用for遍歷,通過隨機訪問太慢慢