Java集合----List

1.List簡介

List接口是Java對線性表(邏輯上的)的特征的抽象莹菱。

2.List接口的實現(xiàn)

2.1ArrayList

最常用的List集合實現(xiàn)凿渊,是一種動態(tài)可增長基于數(shù)組的有序集合。

2.1.1基本特征

①數(shù)據(jù)存儲是基于數(shù)組實現(xiàn)的(默認數(shù)組大小為10)蕊梧;
②添加數(shù)據(jù)時,會首先檢測是否超過數(shù)組容量,如果超過了則需要對數(shù)組進行擴容(擴容采用Arrays.copyOf()方法音榜,代價很高避免擴容這樣的操作);
③刪除數(shù)據(jù)時捧弃,需要將刪除點+1位置開始到數(shù)組末尾的數(shù)據(jù)全部向前移動一位赠叼。
④獲取數(shù)據(jù)很快擦囊,根據(jù)數(shù)組下標可以直接獲取。
⑤此實現(xiàn)不是線程安全的嘴办;

2.1.2 ArrayList的實現(xiàn)

2.1.2.1 屬性

 private transient Object[] elementData;//存儲元素 transient標識的屬性在序列化時并不會被序列化
 private int size;//數(shù)組內(nèi)元素的數(shù)量

2.1.2.2 常用API及特殊API

tip1:因為底層是基于數(shù)組的瞬场,那么自然的在末尾增加移除元素是較容易的,在指定位置插入移除元素就相對的消耗時間了.
tip2:因為底層是基于數(shù)組的涧郊,按下標取元素時間復雜度就是常數(shù)了

2.1.2.2.1 add()系列
public boolean add(E e);//在末尾加入元素
public void add(int index, E element) ;//在指定位置插入元素,包括當前位置元素在內(nèi)以后的元素向右移動(index加1)贯被。 
public boolean addAll(int index, Collection<? extends E> c);//在末尾增加元素列表
public boolean addAll(int index, Collection<? extends E> c);//在指定位置插入元素列表
2.1.2.2.2 remove()系列
public boolean remove(Object o);//根據(jù)指針去除元素
public boolean remove(int index);//根據(jù)游標去除元素
public boolean removeAll(Collection<?> c);//去除c內(nèi)包含的元素
2.1.2.2.3 set()系列
public E set(int index, E element);//替換指定位置的元素
2.1.2.2.4 get()系列
 public E get(int index);//返回制定位置的元素
2.1.2.2.5 subList(int fromIndex, int toIndex)
public List<E> subList(int fromIndex, int toIndex);
//返回當前List中對于(fromIndex,toIndex)部分的引用

注意:和String.subString()完全不一樣,例如:
ArrayList<Object> objs1= new ArrayList<Object>(100);
objs1.subList(0, 5).clear();//objs1 中下標為0,1,2,3,4的數(shù)據(jù)會變成null妆艘;

2.1.2.2.5 trimToSize()彤灶;
public void trimToSize();//將List的capacity削減到和size大小一致;

2.2LinkedList

LinkedList是List接口基于雙向鏈表的實現(xiàn)批旺,基于鏈表使得LinkedList在插入和刪除時更優(yōu)于ArrayList幌陕,而隨機訪問則比ArrayList遜色些。

2.2.1數(shù)據(jù)結(jié)構(gòu)

double-linked.jpg

2.2.2數(shù)據(jù)結(jié)構(gòu)的代碼描述

transient Node<E> first;//LinkedList的首指針
transient Node<E> last;//LinkedList的尾指針
private static class Node<E> {//節(jié)點
  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;
  }
}

2.2.2常用API及其實現(xiàn)

2.2.2.1 add()系列:

public boolean add(E e)朱沃;//末尾追加元素

public boolean add(E e) {
  linkLast(e);
  return true;
}
void linkLast(E e) {
  final Node<E> l = last;//取最后一個元素
  final Node<E> newNode = new Node<>(l, e, null);//構(gòu)造新節(jié)點
  last = newNode;//設(shè)置新節(jié)點為最后的節(jié)點
 if (l == null)//如果為新構(gòu)造的空鏈表苞轿,則把首指針也設(shè)置為尾指針
    first = newNode;
 else
   l.next = newNode;//進行鏈接
   size++;//元素數(shù)量增加
   modCount++;//fast-fail 機制支持
}

objs2.add(index, element);//在指定下標插入元素,涉及到雙向列表的遍歷

public void add(int index, E element) {
  checkPositionIndex(index);//檢測是否查過元素數(shù)量
  if (index == size)//如果是在末尾插入逗物,則直接追加
    linkLast(element);
  else
    linkBefore(element, node(index));//在指定位置插入元素
}
//雙向鏈表的遍歷
Node<E> node(int index) {
  if (index < (size >> 1)) {//在index小于size的一半時搬卒,從first向后遍歷
    Node<E> x = first;
    for (int i = 0; i < index; i++)
      x = x.next;
    return x;
  } else {//在index大于size的一半時,從last向前遍歷
    Node<E> x = last;
    for (int i = size - 1; i > index; i--)
      x = x.prev;
    return x;
  }
}
//插入元素e在succ前面
void linkBefore(E e, Node<E> succ) {
  // assert succ != null;
  final Node<E> pred = succ.prev;
  final Node<E> newNode = new Node<>(pred, e, succ);
  succ.prev = newNode;
  if (pred == null)
    first = newNode;
  else
    pred.next = newNode;
    size++;
    modCount++;
}

public void addFirst(E e)翎卓;//首部添加
public void addLast(E e);//尾部添加
public boolean addAll(Collection<? extends E> c)契邀;//末尾鏈接集合
public boolean addAll(int index, Collection<? extends E> c);//在指定位置插入集合失暴,也涉及到index的遍歷坯门,可參考上面兩個來寫,遍歷找到index位置節(jié)點然后循環(huán)追加逗扒,然后鏈接上古戴。

2.2.2.2 clear():

public void clear();//置空雙向鏈表,同時置空每個節(jié)點的首尾指針矩肩,盡管置空節(jié)點的首尾指針比不必要的但是
-helps a generational GC if the discarded nodes inhabit more than one generation
-is sure to free memory even if there is a reachable Iterator
也就是避免 ‘在這個List的某些特定的節(jié)點仍有外部引用指向時现恼,導致的其他節(jié)點不可被清理’ 涉及到分代GC的原理

public void clear() {
  for (Node<E> x = first; x != null; ) {
    Node<E> next = x.next;
    x.item = null;
    x.next = null;
    x.prev = null;
    x = next;
   }
   first = last = null;
   size = 0;
   modCount++;
}

2.2.2.2 clone()鏈表的克隆:

克隆鏈表后把原鏈表的數(shù)據(jù)遍歷加入

public Object clone() {
  LinkedList<E> clone = superClone();
  // Put clone into "virgin" state
  clone.first = clone.last = null;
  clone.size = 0;
  clone.modCount = 0;
  // Initialize clone with our elements
  for (Node<E> x = first; x != null; x = x.next)
      clone.add(x.item);
   return clone;
}

2.2.2.3 descendingIterator()反向遍歷迭代器:

2.2.2.4 remove():刪除元素

遍歷查找元素然后將前后兩個節(jié)點鏈接起來即可黍檩。

2.2.3 關(guān)于LinkedList的遍歷性能問題

參看這篇文章 http://blog.csdn.net/u010853261/article/details/54143917
不要使用for循環(huán)叉袍,還是用迭代器吧

2.3Vector

ArrayList的線程安全版本,方法上增加synchronized 實現(xiàn)刽酱。

3.fast-fail機制

在AbstractList類中有modCount這么一個字段喳逛,擴展類ArrayList、LinkedList以及Vector中 在對自身的元素進行更改時均會modCount++操作棵里;
Thread a,b 兩個線程對同一個List實例 listTest通過迭代器迭代(迭代期對象持有一個在自身被創(chuàng)建時listTest的modCount的值)润文,如果a線程進行修改導致了modCount++操作姐呐,b線程在的迭代器modCount未進行改變,則b線程迭代會導致 ConcurrentModificationException();而Java并不保證一定能觸發(fā)转唉,所以還是不要在多線程環(huán)境中使用這些實現(xiàn)或者自己在外部提供同步機制

final void checkForComodification() {
  if (modCount != expectedModCount)
     throw new ConcurrentModificationException();
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末皮钠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子赠法,更是在濱河造成了極大的恐慌麦轰,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件砖织,死亡現(xiàn)場離奇詭異款侵,居然都是意外死亡,警方通過查閱死者的電腦和手機侧纯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門新锈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人眶熬,你說我怎么就攤上這事妹笆。” “怎么了娜氏?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵拳缠,是天一觀的道長。 經(jīng)常有香客問我贸弥,道長窟坐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任绵疲,我火速辦了婚禮哲鸳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘盔憨。我一直安慰自己徙菠,他們只是感情好,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布郁岩。 她就那樣靜靜地躺著懒豹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪驯用。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天儒老,我揣著相機與錄音蝴乔,去河邊找鬼。 笑死驮樊,一個胖子當著我的面吹牛薇正,可吹牛的內(nèi)容都是我干的片酝。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼挖腰,長吁一口氣:“原來是場噩夢啊……” “哼雕沿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起猴仑,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤审轮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后辽俗,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疾渣,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年崖飘,在試婚紗的時候發(fā)現(xiàn)自己被綠了榴捡。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡朱浴,死狀恐怖吊圾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情翰蠢,我是刑警寧澤项乒,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站躏筏,受9級特大地震影響板丽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜趁尼,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一埃碱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧酥泞,春花似錦砚殿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至悯姊,卻和暖如春羡藐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背悯许。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工仆嗦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人先壕。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓瘩扼,卻偏偏與公主長得像谆甜,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子集绰,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

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

  • Java集合 作為一個Developer规辱,Java集合類是我們在工作中運用最多的、最頻繁的類栽燕。相比于數(shù)組(Arra...
    賈博巖閱讀 65,493評論 14 103
  • java筆記第一天 == 和 equals ==比較的比較的是兩個變量的值是否相等罕袋,對于引用型變量表示的是兩個變量...
    jmychou閱讀 1,497評論 0 3
  • List是有序,元素可重復的Collection纫谅,實現(xiàn)List接口的常用類有ArrayList炫贤,LinkedLis...
    spiritTalk閱讀 524評論 0 0
  • 一兰珍、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對于byte類型而言...
    龍貓小爺閱讀 4,259評論 0 16
  • 細雪微微,斜風作曉寒询吴,落筆恍覺忽已晚掠河,臨窗燈火疏暗。 京都漫漫猛计,征鴻度玉關(guān)唠摹,莫道此間行路難,人間自是清歡奉瘤。 一年的...
    踏歌娘閱讀 558評論 9 5