jdk源碼之LinkedList

概要

  • 類繼承關系

java.lang.Object
java.util.AbstractCollection<E>
java.util.AbstractList<E>
java.util.AbstractSequentialList<E>
java.util.LinkedList<E>

  • 定義

public class LinkedList<E> extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable{
}

實現(xiàn)

linkedList基于雙向鏈表機制,即集合中的每個元素都知道其前一個元素和后一個元素的位置。

  • 創(chuàng)建
public LinkedList() {
}

創(chuàng)建一個空list吱肌。

public LinkedList(Collection<? extends E> c) {
  this();    
  addAll(c);
}

public boolean addAll(Collection<? extends E> c) {
    return addAll(size, c);
}

public boolean addAll(Collection<? extends E> c) {
    return addAll(size, c);

public boolean addAll(int index, Collection<? extends E> c) {
  checkPositionIndex(index);    
  Object[] a = c.toArray();    
  int numNew = a.length;    

  if (numNew == 0)        
    return false;    

  Node<E> pred, succ;    

  if (index == size) {        
    succ = null;        
    pred = last;    
  } else {        
    succ = node(index);        
    pred = succ.prev;    
  }    

  for (Object o : a) {        
    @SuppressWarnings("unchecked") 
    E e = (E) o;        
    Node<E> newNode = new Node<>(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;    
  }    

  size += numNew;    
  modCount++;    
  return true;}
}

addAll(int, Collection)首先判斷是在鏈表尾部加入集合,還是鏈表中涯呻,分別獲取要插入的位置和要插入位置的前一位置宫盔。
接著插入元素绰疤,這里有個判斷佩研,看是否是空鏈表柑肴,如果是,在循環(huán)的第一次執(zhí)行旬薯,會進入一下代碼:

if (pred == null)    first = newNode;

插入完畢后晰骑,判斷:
如果是在表尾插入,則將last指向最有一個插入元素绊序,
否則些侍,插入的最后一個元素的下一個元素指向addAll傳入的index位置,index位置的前一個元素也指向插入的最后一個元素政模。

  • 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;    
  }
}

由節(jié)點的定義可知,LinkedList是雙鏈表蚂会。

  • 添加元素 add(E)
public boolean add(E e) {    
  linkLast(e);    
  return true;
}

linkLast函數(shù)在表尾添加一個元素:

void linkLast(E e) {    
  final Node<E> l = last;    
  final Node<E> newNode = new Node<>(l, e, null);    
  last = newNode;    
  if (l == null)        
    first = newNode;    
  else        
    l.next = newNode;    
  size++;    
  modCount++;
}

該函數(shù)將新加入的節(jié)點的前一個元素指向原鏈表的最后一個元素淋样,并將原鏈表指向最后一個元素的指針執(zhí)行新添加的元素。
接著做了一個判斷胁住,如果鏈表為空趁猴,鏈表指向第一個元素的指針指向新節(jié)點刊咳,否則,原鏈表的最后一個元素指向新元素儡司。

  • 刪除元素 remove(Object o)
public boolean remove(Object o) {    
  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;
}

如果刪除元素為null, 則unlink所有null元素娱挨,否則,通過equals來判斷捕犬。

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;
}

如果待刪元素是頭節(jié)點跷坝,則頭指針指向該元素的下一個節(jié)點,否則碉碉,該元素的前一個節(jié)點的下一個節(jié)點指向該元素的下一個節(jié)點柴钻,且該元素的前一個節(jié)點指向null。
如果待刪元素是尾節(jié)點垢粮,分析方法同上贴届。

  • 獲取元素 get(int)
public E get(int index) {    
  checkElementIndex(index);    
  return node(index).item;
}

Node<E> node(int index) {    
  // assert isElementIndex(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;    
  }
}

這里有個小技巧,首先判斷當前要獲取的位置是否小于size的一半蜡吧,若小于毫蚓,則從頭開始找,否則從尾部開始找昔善。

注:

  1. LinkedList基于雙向鏈表實現(xiàn)元潘。
  2. 非線程安全。
  3. 查找和刪除需要遍歷耀鸦,插入創(chuàng)建一個新結點柬批,并切換相應元素的前后元素的引用。
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末袖订,一起剝皮案震驚了整個濱河市氮帐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌洛姑,老刑警劉巖上沐,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異楞艾,居然都是意外死亡参咙,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門硫眯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蕴侧,“玉大人,你說我怎么就攤上這事两入【幌” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長择葡。 經(jīng)常有香客問我紧武,道長,這世上最難降的妖魔是什么敏储? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任阻星,我火速辦了婚禮,結果婚禮上已添,老公的妹妹穿的比我還像新娘妥箕。我一直安慰自己,他們只是感情好酝碳,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布矾踱。 她就那樣靜靜地躺著,像睡著了一般疏哗。 火紅的嫁衣襯著肌膚如雪呛讲。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天返奉,我揣著相機與錄音贝搁,去河邊找鬼。 笑死芽偏,一個胖子當著我的面吹牛雷逆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播污尉,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼膀哲,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了被碗?” 一聲冷哼從身側響起某宪,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎锐朴,沒想到半個月后兴喂,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡焚志,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年衣迷,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片酱酬。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡壶谒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出膳沽,到底是詐尸還是另有隱情佃迄,我是刑警寧澤泼差,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站呵俏,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏滔灶。R本人自食惡果不足惜普碎,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望录平。 院中可真熱鬧麻车,春花似錦、人聲如沸斗这。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽表箭。三九已至赁咙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間免钻,已是汗流浹背彼水。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留极舔,地道東北人凤覆。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像拆魏,于是被迫代替她去往敵國和親盯桦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內(nèi)容