Java集合類基礎(List,Set,Map)__Java

來源:互聯網
上載者:User
集合類簡介

Java的集合類主要由兩個介面派生而出:Collection和Map,這兩個介面又包含了一些介面或實作類別。
一個Collection代表一組Object,即Collection的元素(Elements)。一些Collection允許相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供Collection的直接實現,提供的類都是繼承自Collection的“子介面”如List和Set。所以Set、List和Map可以看做集合的三大部分

Collections是一個集合架構的協助類,裡麵包含一些對集合的排序,搜尋以及序列化的操作。

集合架構的優點如下:
(1)使用核心集合類降低開發成本,而非實現我們自己的集合類。
(2)隨著使用經過嚴格測試的集合架構類,代碼品質會得到提高。
(3)通過使用JDK附帶的集合類,可以降低代碼維護成本。
(4)複用性和可操作性。

使用泛型的好處。
(1)泛型允許我們為集合提供一個可以容納的物件類型,因此,如果你添加其它類型的任何元素,它會在編譯時間報錯。這避免了在運行時出現ClassCastException,因為你將會在編譯時間得到報錯資訊。
(2)泛型也使得代碼整潔,我們不需要使用顯式轉換和instanceOf操作符。
(3)它也給運行時帶來好處,因為不會產生類型檢查的位元組碼指令。 遍曆集合的方法:Iterator介面和foreach迴圈

Collection有一個重要的方法:iterator(),返回一個迭代器Iterator,用於遍曆集合的所有元素。Iterator模式可以把訪問邏輯從不同的集合類中抽象出來,從而避免向用戶端暴露集合的內部結構。

每一種集合類返回的Iterator具體類型可能不同,但它們都實現了Iterator介面,因此,我們不需要關心到底是哪種Iterator,它只需要獲得這個Iterator介面即可,這就是介面的好處,物件導向的威力。

迭代器取代了Java集合架構中的Enumeration(遺留類),Iterator更加安全,因為當一個集合正在被遍曆的時候,它會阻止其它線程去修改集合(以拋異常的方式)。要確保遍曆過程順利完成,必須保證遍曆過程中不更改集合的內容(Iterator的remove()方法除外),所以,確保遍曆可靠的原則是:只在一個線程中使用這個集合,或者在多線程中對遍曆代碼進行同步。

Iterator介面提供的三種方法:
(1)boolean hasNext():返回集合裡的下一個元素。
(2)Object next():返回集合裡下一個元素。
(3)void remove();刪除集合裡上一次next方法返回的元素。
典型的用法如下:

public class TestIterator {     public static void main(String[] args) {         //建立一個集合         Collection books = new HashSet();         books.add("輕量級J2EE公司專屬應用程式實戰");         books.add("Struts2權威指南");         books.add("基於J2EE的Ajax寶典");         //擷取books集合對應的迭代器         Iterator<String> it = books.iterator();         while(it.hasNext()) {             String book = it.next();             System.out.println(book);             if (book.equals("Struts2權威指南")) {                 it.remove();                //使用Iterator迭代過程中,不可修改集合元素,下面代碼引發異常                //books.remove(book);             }             //對book變數賦值,不會改變集合元素本身             book = "測試字串";         }         System.out.println(books);     } }

程式運行結果:

Struts2權威指南 基於J2EE的Ajax寶典 輕量級J2EE公司專屬應用程式實戰 [基於J2EE的Ajax寶典, 輕量級J2EE公司專屬應用程式實戰]

說明:
(1)通過語句book = "測試字串"; 對迭代變數book進行賦值時,當我們再次輸出books集合時,集合裡的元素沒有任何變化。即當使用Iterator對集合元素進行迭代時,Iterator並不是把集合元素本身傳給迭代變數,而是把集合元素的值傳給了迭代變數。因為java都是值傳遞,詳見:java參數傳遞的方式。
(2)當使用Iterator來訪問Collection集合元素時,只有通過Iterator的remove方法才能刪除當前元素。其它在遍曆過程中更改集合內容的行為都會引發java.util.ConcurrentModificationExcption異常。

對比一下,for each的方式線程不安全,但簡化了代碼,也不用管是否越界。 List介面

List是有序的Collection,可以有相同的元素,使用此介面能夠精確的控制每個元素插入的位置。使用者能夠使用索引(元素在List中的位置,類似於數組下標)來訪問List中的元素,類似於Java的數組。

除了具有Collection介面必備的iterator()方法外,List還提供一個listIterator()方法,返回一個ListIterator介面,和標準的Iterator介面相比,ListIterator多了一些add()之類的方法,允許添加,刪除,設定元素,還能向前或向後遍曆previous()。

實現List介面的常用類有LinkedList,ArrayList,Vector和Stack(後兩個是遺留類)。 LinkedList類

LinkedList實現了List介面,允許null元素。此外LinkedList提供額外的get,remove,insert方法在LinkedList的首部或尾部。這些操作使LinkedList可被用作堆棧(stack),隊列(queue)或雙向隊列(deque)。擅長頻繁增刪元素。

注意LinkedList沒有同步方法。如果多個線程同時訪問一個List,則必須自己實現訪問同步。一種解決方案是在建立List時構造一個同步的List:

List list = Collections.synchronizedList(new LinkedList(…));
ArrayList類

ArrayList實現了可變大小的數組,允許null元素,沒有同步方法。擅長隨機訪問元素。與Array不同的是,Array可以容納基本類型和對象,而ArrayList只能容納對象。

每個ArrayList執行個體都有一個容量(Capacity),即用於儲存元素的數組的大小。這個容量可隨著不斷添加新元素而自動增加,但是增長演算法並沒有定義。當需要插入大量元素時,在插入前可以調用ensureCapacity方法來增加ArrayList的容量以提高插入效率。 Vector類和Stack 類

作為遺留類不推薦使用。Vector非常類似ArrayList,兩者都是基於索引的,內部由一個數組支援,都維護插入順序。但是Vector是同步的。
Stack繼承自Vector,提供5個額外的方法:基本的push和pop方法,還有peek方法得到棧頂的元素,empty方法測試堆棧是否為空白,search方法檢測一個元素在堆棧中的位置。 Set介面

Set是一種不包含重複的元素的Collection,即任意的兩個元素e1和e2都有e1.equals(e2)=false,Set最多有一個null元素。
請注意:必須小心操作可變對象(Mutable Object)。如果一個Set中的可變元素改變了自身狀態導致Object.equals(Object)=true將導致一些問題。

Set介面有以下幾種實現:
(1)HashSet : 為快速尋找設計的Set,主要的特點是:不能存放重複元素,而且採用散列的儲存方法,所以沒有順序。這裡所說的沒有順序是指元素插入的順序與輸出的順序不一致。
(2)TreeSet : 儲存次序的Set, 底層為樹結構。使用它可以從Set中提取有序的序列。
(3)LinkedHashSet : 具有HashSet的查詢速度,且內部使用鏈表維護元素的順序(插入的次序)。於是在使用迭代器遍曆Set時,結果會按元素插入的次序顯示。 Map介面

常用有HashMap、LinkedHashMap、HashTable和TreeMap。詳情請見:
Java8的HashMap詳解(儲存結構,功能實現,擴容最佳化,安全執行緒,遍曆方法)。
這裡主要講一下,由於作為key的對象將通過計算其散列函數來確定與之對應的value的位置,因此任何作為key的對象都必須實現hashCode和equals方法。
hashCode和equals方法繼承自根類Object,如果你用自訂的類當作key的話,要相當小心,按照散列函數的定義,如果兩個對象相同,即obj1.equals(obj2)=true,則它們的hashCode必須相同,但如果兩個對象不同,則它們的hashCode不一定不同,如果兩個不同對象的hashCode相同,這種現象稱為衝突,衝突會導致操作雜湊表的時間開銷增大,所以盡量定義好的hashCode()方法,能加快雜湊表的操作。
如果相同的對象有不同的hashCode,對雜湊表的操作會出現意想不到的結果(期待的get方法返回null),要避免這種問題,只需要牢記一條:要同時複寫equals方法和hashCode方法,而不要唯寫其中一個。其實最好使用JDK提供的不可變類作為Map的key,可以避免自己實現hashCode()和equals()。 結語

以上就是集合架構相關的介面和類的介紹,最後要注意的是,盡量返回介面而非實際的類型,如返回List而非ArrayList,這樣如果以後需要將ArrayList換成LinkedList時,用戶端代碼不用改變。這就是針對抽象編程。

參考自:大公司最喜歡問的Java集合類面試題
Java集合架構總結—超詳細-適合面試
40個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.