Java高級特性之集合

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值可以重複;
  • keyvalue是多(一)對一的關係;
  • 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         }