日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

collection 源码

發布時間:2025/7/14 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 collection 源码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自:http://blog.csdn.net/longlong2015/article/details/48174421

http://blog.csdn.net/mra__s__/article/details/55517204

http://www.cnblogs.com/chenssy/p/3746600.html

?

JDK 1.7源碼閱讀筆記(三)集合類之LinkedList

標簽:?jdklinkedlist源碼閱讀 ?分類: JDK源碼(6)?

目錄(?)[+]

前言

  (1)LinkedList的內部實現是雙向鏈表,繼承了AbstractSequentialList,實現了List, Deque, Cloneable,?Java.io.Serializable接口,因此LinkdeList本身支持就支持雙端隊列操作。LinkedList**允許所有元素(包括 null)**。除了實現 List 接口外,LinkedList 類還為在列表的開頭及結尾 get、remove 和 insert 元素提供了統一的命名方法。這些操作允許將鏈接列表用作堆棧、隊列或雙端隊列。

  此類實現 Deque 接口,為 add、poll 提供先進先出隊列操作,以及其他堆棧和雙端隊列操作。?
  LinkedList與ArrayList一樣實現List接口,只是ArrayList是List接口的大小可變數組的實現,LinkedList是List接口鏈表的實現。基于鏈表實現的方式使得LinkedList在插入和刪除時更優于ArrayList,而隨機訪問則比ArrayList遜色些。

  (2)此實現不是同步的。如果多個線程同時訪問一個鏈接列表,而其中至少一個線程從結構上修改了該列表,則它必須 保持外部同步。(結構修改指添加或刪除一個或多個元素的任何操作;僅設置元素的值不是結構修改。)這一般通過對自然封裝該列表的對象進行同步操作來完成。如果不存在這樣的對象,則應該使用 Collections.synchronizedList 方法來“包裝”該列表。最好在創建時完成這一操作,以防止對列表進行意外的不同步訪問,如下所示:

List list = Collections.synchronizedList(new LinkedList(...));

  (3) 此類的 iterator 和 listIterator 方法返回的迭代器是快速失敗 的:在迭代器創建之后,如果從結構上對列表進行修改,除非通過迭代器自身的 remove 或 add 方法,其他任何時間任何方式的修改,迭代器都將拋出 ConcurrentModificationException。因此,面對并發的修改,迭代器很快就會完全失敗,而不冒將來不確定的時間任意發生不確定行為的風險。

  注意,迭代器的快速失敗行為不能得到保證,一般來說,存在不同步的并發修改時,不可能作出任何硬性保證??焖偈〉鞅M最大努力拋出 ConcurrentModificationException。因此,編寫依賴于此異常的程序的方式是錯誤的,正確做法是:迭代器的快速失敗行為應該僅用于檢測程序錯誤。

  (4)和ArrayList類似,在類內部同樣出現了transient關鍵字,這在ArrayList中已經解釋過了,在這里不做過多的解釋了。

transient int size = 0;transient Node<E> first;transient Node<E> last;
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

源碼

1>LinkedList內部通過Node來抽象一個節點,結點包括值和前向指針和后向指針。Node的定義是在LinkedList內部,作為靜態內部類存在。

private static class Node<E> { E item;//結點的值 Node<E> next;//結點的后向指針 Node<E> prev;//結點的前向指針 //構造函數中已完成Node成員的賦值 Node(Node<E> prev, E element, Node<E> next) { this.item = element;//結點的值賦值為element this.next = next;//后向指針賦值 this.prev = prev;//前向指針賦值 } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

2>LinkedList 的關鍵源碼

//LinedList繼承了AbstractSequentialList,支持泛型 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() { } //按c里面的元素生成一個LinkedList public LinkedList(Collection<? extends E> c) { this();//調用空的構造函數 addAll(c);//將c里面的元素添加到空鏈表尾部 } //首部增加結點,結點的值為e private void linkFirst(E e) { final Node<E> f = first;//f指向頭結點 //生成一個新結點,結點的值為e,其前向指針為null,后向指針為f final Node<E> newNode = new Node<>(null, e, f); //first指向新生成的結點,f保存著老的頭結點信息 first = newNode; if (f == null) //如果f為null,則表示整個鏈表目前是空的,則尾結點也指向新結點 last = newNode; else //f(老的頭結點)的前向指針指向最新的結點信息 f.prev = newNode; size++;//元素個數+1. modCount++;//修改次數+1 } //尾部增加結點,結點的值為e void linkLast(E e) { final Node<E> l = last;//l指向尾結點 //生成一個新結點,結點的值為e,其前向指針為l,后向指針為null final Node<E> newNode = new Node<>(l, e, null); //last指向新生成的結點,l保存著老的尾結點信息 last = newNode; if (l == null) //如果l為null,則表示整個鏈表目前是空的,則頭結點也指向新結點 first = newNode; else //l(老的尾結點)的后向指針指向最新的結點信息 l.next = newNode; size++;//元素個數+1 modCount++;//修改次數+1 } //非空結點succ之前插入新結點,新結點的值為e void linkBefore(E e, Node<E> succ) { // assert succ != null;//外界調用需保證succ不為null,否則程序會拋出空指針異常 final Node<E> pred = succ.prev;//pred指向succ的前向結點 //生成一個新結點,結點的值為e,其前向指針指向pred,后向指針指向succ final Node<E> newNode = new Node<>(pred, e, succ); succ.prev = newNode;//succ的前向指針指向newNode if (pred == null) //如果pred為null,則表示succ為頭結點,此時頭結點指向最新生成的結點newNode first = newNode; else //pred的后向指針指向新生成的結點,此時已經完成了結點的插入操作 pred.next = newNode; size++;//元素個數+1 modCount++;//修改次數+1 } //刪除頭結點,并返回該結點的值 private E unlinkFirst(Node<E> f) { // assert f == first && f != null;//需確保f為頭結點,且鏈表不為Null final E element = f.item;//獲得結點的值 final Node<E> next = f.next;//next指向f的后向結點 f.item = null;//釋放數據結點 f.next = null;//釋放f的后向指針 first = next;//first指向f的后向結點 if (next == null) //如果next為null,則表示f為last結點,此時鏈表即為空鏈表 last = null; else //修改next的前向指針,因為first結點的前向指針為null next.prev = null; size--;//元素個數-1 modCount++;//修改次數+1 return element; } //刪除尾結點,并返回尾結點的內容 private E unlinkLast(Node<E> l) { // assert l == last && l != null;//需確保l為尾結點,且鏈表不為null final E element = l.item;//獲得結點的值 final Node<E> prev = l.prev;//prev執行l的前向結點 l.item = null;//釋放l結點的值 l.prev = null; //釋放l結點的前向指針 last = prev;//last結點指向l的前向結點 if (prev == null) //如果prev為null,則表示l為first結點,此時鏈表即為空鏈表 first = null; else //修改prev的后向指針,因為last結點的后向指針為null prev.next = null; size--;//元素個數-1 modCount++;//修改次數+1 return element; } //刪除結點x E unlink(Node<E> x) { // assert x != null;//需確保x不為null,否則后續操作會拋出空指針異常 final E element = x.item;//保存x結點的值 final Node<E> next = x.next;//next指向x的后向結點 final Node<E> prev = x.prev;//prev指向x的前向結點 if (prev == null) { //如果prev為空,則x結點為first結點,此時first結點指向next結點(x的后向結點) first = next; } else { prev.next = next;//x的前向結點的后向指針指向x的后向結點 x.prev = null;//釋放x的前向指針 } if (next == null) { //如果next結點為空,則x結點為尾部結點,此時last結點指向prev結點(x的前向結點) last = prev; } else { next.prev = prev;//x的后向結點的前向指針指向x的前向結點 x.next = null;//釋放x的后向指針 } x.item = null;//釋放x的值節點,此時x節點可以完全被GC回收 size--;//元素個數-1 modCount++;//修改次數+1 return element; } //獲得頭結點的值 public E getFirst() { final Node<E> f = first;//f指向first結點 if (f == null)//此時鏈表為空 throw new NoSuchElementException(); return f.item;//返回first結點的值 } //獲得尾結點的值 public E getLast() { final Node<E> l = last;//l指向last結點 if (l == null)//此時鏈表為空 throw new NoSuchElementException(); return l.item;//返回last結點的值 } //移除頭結點 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);//摘除尾結點 } //添加到頭結點,結點的值為e public void addFirst(E e) { linkFirst(e);//添加到頭部 } //添加到尾結點,結點值為e public void addLast(E e) { linkLast(e);//添加到尾部 } //判斷元素(值為o)是o否在鏈表中 public boolean contains(Object o) { return indexOf(o) != -1;//定位元素 } //返回元素個數 public int size() { return size; } //添加元素,元素值為e public boolean add(E e) { linkLast(e);//添加到鏈表尾部 return true; } //移除值為o的元素,o可以為null,找到一個刪除即返回 public boolean remove(Object o) { if (o == null) {//元素為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);//添加到鏈表尾部 } //第序號為index處,添加c中所有的元素到當前鏈表中(后向添加的) public boolean addAll(int index, Collection<? extends E> c) { checkPositionIndex(index);//判斷index是否超出界 Object[] a = c.toArray();//將集合轉換為數組 int numNew = a.length; if (numNew == 0) return false; Node<E> pred, succ; if (index == size) {//如果index為元素個數,即第index個結點為尾結點 succ = null; pred = last;//指向為結點 }

轉載于:https://www.cnblogs.com/thxu/p/7406971.html

總結

以上是生活随笔為你收集整理的collection 源码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。