Java集合框架
一、Java集合框架概述
1、陣列與集合的區別:
1)陣列長度不可變化而且無法儲存具有對映關係的資料;集合類用於儲存數量不確定的資料,以及儲存具有對映關係的資料。
2)陣列元素既可以是基本型別的值,也可以是物件;集合只能儲存物件。
2、Java集合類主要由兩個根介面Collection和Map派生出來的,Collection派生出了三個子介面:List、Set、Queue(Java5新增的佇列),因此Java集合大致也可分成List(有序、可重複集合、可直接根據元素的索引來訪問)、Set(無序、不可重複集合、只能根據元素本身來訪問)、Queue(佇列集合)、Map(儲存key-value對的集合,可根據元素的key來訪問value)這四種。
二、Java集合常見介面及實現類
1、Collection介面常見方法
2、List集合
實現List介面的集合主要有:ArrayList、LinkedList、Vector、Stack。
它們都可以容納所有型別的物件,包括 null,允許重複,並且都保證元素的儲存順序。(可重複,有順序)
1)ArrayList
ArrayList 對陣列進行了封裝,實現了長度可變的陣列(動態陣列),和陣列採用相同儲存方式,在記憶體中分配連續的空間,它的優點在於遍歷元素和隨即訪問元素的效率比較高。
ArrayList特點:執行緒不安全,查詢速度快;底層資料結構是陣列結構;擴容增量:原容量的 1.5倍, 如 ArrayList的容量為10,一次擴容後是容量為15。
2)LinkedList
LinkedList是List介面的另一個實現,除了可以根據索引訪問集合元素外,LinkedList還實現了Deque介面,可以當作雙端佇列來使用,也就是說,既可以當作“棧”使用,又可以當作佇列使用。
LinkedList 採用連結串列儲存方式,優點在於插入、刪除元素時效率比較高,它提供了額外的 addFirst()、addLast()、removeFirst()和 removeLast()等方法,可以在LinkedList 的首部或尾部進行插入或者刪除操作。
3)Vector
與ArrayList相似,但是Vector是同步的。所以說Vector是執行緒安全的動態陣列。它的操作與ArrayList幾乎一樣。
3、Set集合
實現Set集合的介面主要有:HashSet、TreeSet、LinkedHashSet;
Set集合與Collection的方法相同,由於Set集合不允許儲存相同的元素,所以如果把兩個相同元素新增到同一個Set集合,則新增操作失敗,新元素不會被加入,add()方法返回false。(無序、不重複)
1)HashSet
HashSet是按照hash演算法來儲存元素的,因此具有很好的存取和查詢效能。
HashSet儲存原理如下:
當向HashSet集合儲存一個元素時,HashSet會呼叫該物件的hashCode()方法得到其hashCode值,然後根據hashCode值決定該物件的儲存位置。HashSet集合判斷兩個元素相等的標準是(1)兩個物件通過equals()方法比較返回true;(2)兩個物件的hashCode()方法返回值相等。因此,如果(1)和(2)有一個不滿足條件,則認為這兩個物件不相等,可以新增成功。如果兩個物件的hashCode()方法返回值相等,但是兩個物件通過equals()方法比較返回false,HashSet會以鏈式結構將兩個物件儲存在同一位置,這將導致效能下降,因此在編碼時應避免出現這種情況。
HashSet查詢原理如下:
基於HashSet以上的儲存原理,在查詢元素時,HashSet先計算元素的HashCode值(也就是呼叫物件的hashCode方法的返回值),然後直接到hashCode值對應的位置去取出元素即可,這就是HashSet速度很快的原因。
HashSet特點:
不能保證元素的順序;集合元素值可以是null;執行緒不安全,存取速度快;底層實現是一個HashMap(儲存資料),實現Set介面;預設初始容量為16;載入因子為0.75:即當 元素個數 超過 容量長度的0.75倍 時,進行擴容;擴容增量:原容量的 1 倍;如 HashSet的容量為16,一次擴容後是容量為32。
2)LinkedHashSet
LinkedHashSet是HashSet的一個子類,具有HashSet的特性,也是根據元素的hashCode值來決定元素的儲存位置。但它使用連結串列維護元素的次序,元素的順序與新增順序一致。由於LinkedHashSet需要維護元素的插入順序,因此效能略低於HashSet,但在迭代訪問Set裡的全部元素時由很好的效能。
3)TreeSet
TreeSet可以保證元素處於排序狀態,它採用紅黑樹的資料結構來儲存集合元素。TreeSet支援兩種排序方法:自然排序和定製排序,預設採用自然排序。
♦ 自然排序
TreeSet會呼叫集合元素的compareTo(Object obj)方法來比較元素的大小關係,然後將元素按照升序排列,這就是自然排序。如果試圖將一個物件新增到TreeSet集合中,則該物件必須實現Comparable介面,否則會丟擲異常。當一個物件呼叫方法與另一個物件比較時,例如obj1.compareTo(obj2),如果該方法返回0,則兩個物件相等;如果返回一個正數,則obj1大於obj2;如果返回一個負數,則obj1小於obj2。
♦ 定製排序
想要實現定製排序,需要在建立TreeSet集合物件時,提供一個Comparator物件與該TreeSet集合關聯,由Comparator物件負責集合元素的排序邏輯。
綜上:自然排序實現的是Comparable介面,定製排序實現的是Comparator介面。
4、Map集合
Map介面採用鍵值對Map<K,V>的儲存方式,儲存具有對映關係的資料,因此,Map集合裡儲存兩組值,一組值用於儲存Map裡的key,另外一組值用於儲存Map裡的value,key和value可以是任意引用型別的資料。key值不允許重複,可以為null。如果新增key-value對時Map中已經有重複的key,則新新增的value會覆蓋該key原來對應的value。
常用實現類主要有HashMap、LinkedHashMap、TreeMap。
1)HashMap
對於HashMap而言,key是唯一的,不可以重複的。所以,以相同的key 把不同的value插入到 Map中會導致舊元素被覆蓋,只留下最後插入的元素。不過,同一個物件可以作為值插入到map中,只要對應的key不一樣 。
HashMap由陣列+連結串列組成的,陣列是HashMap的主體,連結串列則是主要為了解決雜湊衝突而存在的。
HashMap工作原理如下:
HashMap基於hashing原理,通過put()和get()方法儲存和獲取物件。當我們將鍵值對傳遞給put()方法時,它呼叫建物件的hashCode()方法來計算hashCode值,然後找到bucket位置來儲存值物件。當獲取物件時,通過建物件的equals()方法找到正確的鍵值對,然後返回物件。HashMap使用連結串列來解決碰撞問題,當發生碰撞了,物件將會儲存在連結串列的下一個節點中。
HashMap特點:
- Map提供了一種對映關係,元素是以鍵值對(key-value)的形式儲存的,能根據key快速查詢value;
- Map中的鍵值對以Entry型別的物件例項形式存在;
- key值不能重複,value值可以重複;
- key對value是多(一)對一的關係;
- Map介面提供了返回key值集合、value值集合、Entry值集合,的方法;
- Map支援泛型,形式如:Map<K,V>;
- 預設初始容量為16;
- 載入因子為0.75:即當 元素個數 超過 容量長度的0.75倍 時,進行擴容;
- 擴容增量:原容量的 1 倍。
2)LinkedHashMap
LinkedHashMap使用雙向連結串列來維護key-value對的次序(其實只需要考慮key的次序即可),該連結串列負責維護Map的迭代順序,與插入順序一致,因此效能比HashMap低,但在迭代訪問Map裡的全部元素時有較好的效能。
大多數情況下,只要不涉及執行緒安全問題,Map基本都可以使用HashMap,不過HashMap有一個問題,是迭代HashMap的順序並不是HashMap放置的順序,也就是無序。HashMap的這一缺點往往會帶來困擾,因為有些場景,我們期待一個有序的Map。這個時候,LinkedHashMap就閃亮登場了,它雖然增加了時間和空間上的開銷,但是通過維護一個執行於所有條目的雙向連結串列,LinkedHashMap保證了元素迭代的順序。該迭代順序可以是插入順序或者是訪問順序。
LinkedHashMap可以認為是HashMap+LinkedList,即它既使用HashMap運算元據結構,又使用LinkedList維護插入元素的先後順序。
LinkedHashMap的基本實現思想就是----多型。
3)TreeMap
TreeMap是SortedMap的實現類,是一個紅黑樹的資料結構,每個key-value對作為紅黑樹的一個節點。TreeMap儲存key-value對時,需要根據key對節點進行排序。TreeMap也有兩種排序方式:
♦ 自然排序:TreeMap的所有key必須實現Comparable介面,而且所有的key應該是同一個類的物件,否則會丟擲ClassCastException。
♦ 定製排序:建立TreeMap時,傳入一個Comparator物件,該物件負責對TreeMap中的所有key進行排序。
TreeMap特點:
·TreeMap是非執行緒安全的;
·TreeMap是用鍵來進行升序順序來排序的。通過Comparable 或 Comparator來排序;
·和HashMap一樣,如果插入重複的元素,後面的元素會覆蓋前面的;
·鍵不可以為null(如果比較器對null做了處理,就可以為null),但是值可以為null。
5、遍歷
第一種:for迴圈遍歷
1 for (int i = 0; i < heros.size(); i++) { 2 Hero h = heros.get(i); 3 System.out.println(h); 4 }
第二種:迭代器遍歷
1 System.out.println("--------使用while的iterator-------"); 2 Iterator<Hero> it= heros.iterator(); 3 //從最開始的位置判斷"下一個"位置是否有資料 4 //如果有就通過next取出來,並且把指標向下移動 5 //直到"下一個"位置沒有資料 6 while(it.hasNext()){ 7 Hero h = it.next(); 8 System.out.println(h); 9 } 10 //迭代器的for寫法 11 System.out.println("--------使用for的iterator-------"); 12 for (Iterator<Hero> iterator = heros.iterator(); iterator.hasNext();) { 13 Hero hero = (Hero) iterator.next(); 14 System.out.println(hero); 15 }
第三種:增強for迴圈
1 System.out.println("--------增強型for迴圈-------"); 2 for (Hero h : heros) { 3 System.out.println(h); 4 }