java 集合類

來源:互聯網
上載者:User

標籤:boolean   缺點   move   方式   複製   collect   判斷   排列   指定位置   

1. Java集合架構圖

 

 

所示:Java有兩類集合,線性表(Collection子類)和索引值對(Map子類)

2. Java集合架構圖-2

 

 

3. 線性表

ArrayList、Vector的引入

l  數組在使用上有局限性:建立後無法改變儲存大小。

代碼示意:int[] iAry=new int[3]; iAry[0]=0;iAry[3];//err

l  此時可用動態數組類ArrayList或Vector:

ArrayList<Integer> ary=new ArrayList<Integer> ();

ary.add(0);…ary.add(3);

ary空間無限制,當空間無法容納時會重新開闢更大空間。

l  ArrayList和Vector的異同:

相同點:

都是基於數組來實現的;都可從指定位置取得元素,從容器的末尾

增加和刪除元素都非常的有效,能在一個常數級的時間(O(1))內完成。但是

從一個其他的位置增加和刪除一個元素頗費時,需要的時間為O(n-i),這裡

的n代表元素個數,i代表要增加和刪除的元素所在的位置。

差別:

 1、Vector法都是同步的,即安全執行緒,而ArrayList不考慮安全執行緒,ArrayList的效能比Vector好;

 2、 當添加元素超容量時,Vector容量翻倍,而ArrayList增加50%(更節約記憶體空間)。 所以,在單線程裡,盡量用ArrayList。

l  ArrayList的優缺點

以數組實現。節約空間,但數組有容量限制。超出限制時會增加50%容量,用System.arraycopy()複製到新的數組,因此最好能給出數組大小的預估值。預設第一次插入元素時建立大小為10的數組。

按數組下標訪問元素--get(i)/set(i,e) 的效能很高,這是數組的基本優勢。

直接在數組末尾加入元素--add(e)的效能也高,但如果按下標插入、刪除元素--add(i,e), remove(i), remove(e),則要用System.arraycopy()來移動部分受影響的元素,效能就變差了,這是基本劣勢。

 

l  LinkedList的結構

 

 

l  LinkedList的優缺點

以雙向鏈表實現。鏈表無容量限制,但雙向鏈表本身使用了更多空間,也需要額外的鏈表指標操作。

按下標訪問元素--get(i)/set(i,e) 要悲劇的遍曆鏈表將指標移動到位(如果i>數組大小的一半,會從末尾移起)。

插入、刪除元素時修改前後節點的指標即可,但還是要遍曆部分鏈表的指標才能移動到下標所指的位置,只有在鏈表兩頭的操作--add(), addFirst(),removeLast()或用iterator()上的remove()能省掉指標的移動。

 

 

 

l  ArrayList與LinkedList的比較

ArrayList基於數組:便於索引,但不便於插入刪除(需要移動元素);

LinkedList基於鏈表:插入和刪除只需修改指標,但不能隨機存取(需從head找起)

代碼理解:

List<String> shenXiao = new LinkedList<String>(); shenXiao.add("子(zǐ)");

shenXiao.add("醜(chǒu)");

shenXiao.add("卯(mǎo)"); shenXiao.add("辰(chén)");

shenXiao.add("巳(sì)"); shenXiao.add("午(wǔ)");

shenXiao.add("未(wèi)"); shenXiao.add("申(shēn)");

shenXiao.add("酉(yǒu)"); shenXiao.add("戌(xū)");

shenXiao.add("亥(hài)"); shenXiao.add(2, "(yín)");

System.out.println(shenXiao);//自動遍曆[..寅(yín)..亥(hài)]

 

l  Set

作為Collection介面的重要子介面,Set介面是一個不包含重複元素,且元素排列無序的集合,並且最多包含一個 null 元素,也被稱為集。

Set介面的方法和Collection介面的方法大體相同,但在遍曆時只能通過Iterator()方法擷取迭代器進行迭代。

Set中的add方法不同於Collection介面,有一個boolean類型的傳回值,當集合中含有與某個元素equals相等的元素時返回false,無法添加,否

則返回true。

Set中的Iterator方法返回的返回的元素沒有特定的順序(除非此 set 是某個提供順序保證的類的執行個體)。

 

 

 

l  HashSet

HashSet類是Set介面的重要實作類別,由雜湊表(實際上是一個 HashMap 執行個體)支援。它不保證 set 的迭代順序;特別是它不保證該順序恒久不變。

Set介面是通過equals方法來比較兩元素是否相同的,但是如果有1000個元素,那麼再添加一個元素,就要比較1000次,效率嚴重降低。所以HashSet類底層採用了HashMap來儲存元素,而HashMap採用了雜湊表的原理。

因此HashSet類按照雜湊演算法來存取對象,當向集合中加入一個新對象時,會調用對象的HashCode()方法得到對象的雜湊碼,然後根據這個碼計算出對象在集合中儲存的位置。 HashCode()方法實際上是返回的Object Storage Service的物理地址。

所以總的來說,HashSet是通過兩元素的HashCode()方法和equals()方法來判斷兩元素是否相等的。

所以當我們使用HashSet添加元素時一定要重寫該元素的HashCode方法和equals方法。並且,參與計算兩個方法傳回值的關鍵屬性應該相同。 程式碼範例:HashSetDemo.java

 

l  TreeSet

TreeSet是一個有序集合,TreeSet中的元素將按照升序排列,預設是按照自然排序進行排列,意味著TreeSet中的元素要實現Comparable介面。

在類上implement Comparable重寫compareTo()方法,在方法內定義比較演算法, 根據大小關係, 返回正數負數或零,在使用TreeSet儲存物件的時候, add()方法內部就會自動調用compareTo()方法進行比較。

代碼:自訂類做元素

必須實現Comparable,否則TreeSet無法add()

 

 

l  HashMap

對於 HashMap 及其子類而言,它們採用 Hash 演算法來決定集合中元素的儲存位置。

當系統開始初始化 HashMap 時,系統會建立一個Entry 數組,這個數組裡可以儲存元素的位置被稱為“桶(bucket)”,每個 bucket 都有其指定索引,系統可以根據其索引快速存取該 bucket 裡儲存的元素。

無論何時,HashMap 的每個“桶”只儲存一個元素(也就是一個 Entry),由於Entry 對象可以包含一個引用變數(就是 Entry 構造器的的最後一個參數)用於指向下一個 Entry,因此可能出現的情況是:HashMap 的 bucket 中只有一個Entry,但這個 Entry 指向另一個 Entry ——這就形成了一個 Entry 鏈。:

 

 

 

l  TreeMap和HashMap的差別

HashMap通過hashcode對其內容進行快速尋找;而TreeMap基於紅/黑樹狀結構實現的,其所有的元素都保持著某種固定的順序,如自然順序或自訂順序。

在Map中插入、刪除和定位元素,HashMap是最好的選擇。但如果要按自然順序或自訂順序遍曆鍵,那麼TreeMap會更好。

註:

1.同樣的對比有TreeSet和HashSet,因為TreeSet基於TreeMap, HashSet基於HashMap

2.使用HashMap要求添加的鍵類需明確實現hashCode()、 equals()。

 

 

 

l  索引值對-Hash演算法

Hash表引入原因:數組定址容易,插入和刪除困難; 而鏈表定址困難,插入和刪除容易。雜湊表可綜合兩者的優點,即,定址容易,插入刪除也容易的資料結構。

Hash(散列)演算法,把任意長度的輸入,用演算法函數變換成固定長度的輸出 (散列值)。不同的輸入可能會散列成相同散列值。

Hash表有多種實現,以拉鏈法(鏈表的數組)解釋: ? 左邊數組,數組每個元素中 包括一個指標,指向一個鏈表的頭。根據元素的一些特徵把元素分配到不同的鏈表中去,也是根據這些特徵,找到正確的鏈表,再從鏈表中找出這個元素。

散列法:元素特徵轉變為數組下標的方法就是散列法,使用除法散列法:index = value % 13

 

 

索引值對-Hash演算法  HashCode的理解

Hashcode(散列碼):每個對象都會有一個int型的hashcode,代表它在記憶體中的位置。

Object中的equals方法是指比較兩個對象是不是指向同一個引用。hashcode方法返回hashCode的值;Object規範裡規定:如果兩個對象根據equals(Object)方式是相等的,那麼這兩個對象的hashCode一定要相等,所以記住:重寫equals方法後,請重寫hashCode方法。

 

l  索引值對

HashMap和Hashtable

Hashtable繼承自Dictionary類,而HashMap是Map介面的一個實現。

代碼:(HashMap改為Hashtable,練習)

 

 

 

主要差別:

1 HashMap允許null key和null value,而hashtable不允許;

2 HashMap是Hashtable的輕量級實現(非安全執行緒的實現),效率高;

3 空間:載入因子預設都為0.75;初始容量Hashtable為11,而HashMap為16。 增加方式Hashtable為 oldSize*2+1,HashMap為oldSize *2。

 

l  列舉程式訪問集合對象

Iterator模式是用於遍曆集合類的標準存取方法。它可以把訪問邏輯從不同類型的集合類中抽象出來,從而避免向用戶端暴露集合的內部結構。

例如,如果沒有使用Iterator,遍曆一個數組的方法是使用索引:

for(int i=0; i<array.size(); i++) { ... get(i) ... } 而訪問一個鏈表(LinkedList)又必須使用while迴圈:while((e=e.next())!=null) { ... e.data() ... } 以上兩種方法用戶端都必須事Crowdsourced Security Testing道集合的內部結構,存取碼和集合本身是緊耦合。無法將訪問邏輯從集合類和用戶端代碼中分離出來,每一種集合對應一種遍曆方法,用戶端代碼無法複用。更恐怖的是,如果以後需要把ArrayList更換為LinkedList,則原來的用戶端代碼必須全部重寫。

為解決以上問題,Iterator模式總是用同一種邏輯來遍曆集合:

for(Iterator it = c.iterater(); it.hasNext(); ) { ... } 這樣一來用戶端自身不維護遍曆集合的"指標",所有的內部狀態(如當前元素位置,是否有下一個元素)都由Iterator來維護,而這個Iterator由集合類通過Factory 方法產生,因此,它知道如何遍曆整個集合。

用戶端從不直接和集合類打交道,它總是控制Iterator,向它發送"向前","向後","取

通過列舉程式訪問線性集合 

 

 

通過列舉程式訪問HashMap

 

 

 

泛型

 

泛型:即參數化型別,所操作的資料類型被指定為一個參數。 ?

這種參數類型可以用在類、介面和方法的建立中(即,泛型類、泛型介面、

泛型方法)。

泛型好處:編譯時間可檢測類型錯誤;避免了強制類型轉換(自動和隱式 ?

的),提高代碼的重用性。

例:

 

 

以上的List就是泛型介面、ArrayList就是泛型類、 add()和get()是泛型方法

註:集合架構,都已經成為泛型化了。

泛型的規則 

 

泛型定義代碼舉例

 

 

 

類型萬用字元?引入原因:

 

 

泛型的繼承,代碼說明:

 

 

 

l  淺拷貝與Clone

有時我們需要複製對象:

 

 

測試:

 

 

 

l  淺拷貝與Clone(續)

分析,從上面代碼運行結果看:

成員變數為基本類型(外加String類型—內容不變性),只要super.clone()就可

拷貝。但數組或複雜類型(參考型別)時,就必須實現深度clone

l  深度clone(本例):

 

 

 

 

l  深度clone()

容器類成員,需逐個元素複製,以ArrayList為例

 

 

 

java 集合類

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.