1. 程式人生 > >Java集合入門總結

Java集合入門總結

本文記錄Java集合學習筆記

目錄1,Java集合類介紹

Java集合類介紹
Java集合類架構層次
Java集合類應用
Java集合類操作

集合類主要負責儲存、盛裝其他資料,因此集合類也被稱為容器類。相比陣列,當需要儲存一個可以動態增長的資料(在編譯時無法確定具體的數量),java的集合類就是一個很好的設計方案了。

集合介面分為:Collection和Map。list、set實現了Collection介面

Collection和Map的區別在於容器中每個位置儲存的元素個數:

Collection 每個位置只能儲存一個元素(物件)
Map儲存的是"鍵值對",就像一個小型資料庫。我們可以通過"鍵"找到該鍵對應的"值"

2,Java集合類架構層次



3,Java集合類應用

1)Set

HashSet

 equals()決定是否可以加入HashSet、而hashCode()決定存放的位置,它們兩者必須同時滿足才能允許一個新元素加入HashSet

如果兩個物件的hashCode相同,但是它們的equlas返回值不同,HashSet會在這個位置用鏈式結構來儲存多個物件。而HashSet訪問集合元素時也是根據元素的HashCode值來快速定位的,這種鏈式結構會導致效能下降。

LinkedHashSet

HashSet的子類,根據元素的hashCode值來決定存放位置,同時使用連結串列維護元素的次序,看起來是以插入的順序儲存的,遍歷時會按照新增順序訪問。

TreeSet

使用紅黑樹的資料結構來儲存集合元素

1. 自然排序:
TreeSet會呼叫集合元素的compareTo(Object obj)方法來比較元素之間的大小關係,根據紅黑樹結構找到它的儲存位置,然後將集合元素按升序排序,即自然排序。如果試圖把一個物件新增到TreeSet時,則該物件的類必須實現Comparable介面,否則程式會丟擲異常。

如果兩個物件通過compareTo(Object obj)方法比較相等,新物件將無法新增到TreeSet集合中(牢記Set是不允許重複的概念)。

2.定製排序:

在建立TreeSet集合物件時,提供一個函式式介面Comparator的物件與該TreeSet集合關聯,負責集合元素的排序邏輯。

EnumSet

在內部以位向量的形式儲存,以列舉值在Enum類內的定義順序來決定集合元素的順序。

各Set實現類的效能
1,只有當需要保持一個排序的Set時,才應該使用TreeSet,否則都應該使用效能總是比TreeSet好的HashSet。
2,LinkedHashSet對於普通的插入、刪除操作比HashSet慢,但遍歷更快。
3,EnumSet是所有Set中效能最好的,但只能儲存同一個列舉類的列舉值作為集合元素。
4,這三個實現類都是執行緒不安全的,通常可以使用Collections工具類的synchronizeSortedSet方法來包裝該Set集合,此操作最好在建立時進行。


2)List

有序,可重複,允許插入null物件,使用索引來訪問指定位置的集合元素其判斷兩個物件只要通過equals()方法比較返回true即可。

List實現了Iterator介面的子介面ListIterator,在Iterator基礎上增加了如下方法:

boolean hasPrevious()
Object previous()
void add(Object o):在指定位置插入一個元素

List另外提供了一個listIterator()方法,返回一個ListIterator物件。

ArrayList和Vector實現類

都是基於陣列實現的List類,initialCapacity引數來設定該陣列的長度,預設長度為10 。當新增大量元素時,可以使用ensureCapacity(int minCapacity)方法一次性增加initialCapacity大小,

void trimToSize():調整集合的Object[]陣列長度為當前元素的個數,以減少佔用的儲存空間。

Vector是古老的集合,是執行緒安全的,但是具有很多缺點,應儘量避免使用。

即使需要保證LIst集合執行緒安全,也不推薦使用Vector,可以用Collections工具類包裝ArrayList變成執行緒安全的。

Vector還有一個Stack子類,LIFO容器。也是一個古老的集合,需要棧結構時可以使用ArrayDeque代替。


3)Queue集合

Queue用於模擬佇列這種資料結構,通常是FIFO容器,Queue介面只有一個PriorityQueue實現類,除此之外還有一個Deque介面,Deque代表一個雙端佇列,也可以當成棧來使用,Java為Deque提供了ArrayDeque和LinkedList實現類

PriorityQueue

時一個比較標準的佇列實現類,其儲存佇列元素的順序時按佇列元素的大小進行重新排序。不允許插入null元素,排序方式有自然排序和定製排序,基本和TreeSet一致。

ArrayDeque

基於陣列實現的雙端佇列,ArrayList和ArrayDeque兩個集合類的實現機制基本相似建立Deque時同樣可指定一個numElements引數,指定Object[]陣列的長度;預設長度為16;

LinkedList

同時時List和Deque的實現類,和ArrayList、ArrayDeque完全不同,它內部是使用連結串列的形式來儲存集合中的元素,因此隨機訪問效能較差,但在插入、刪除元素時效能比較出色。總體上來說ArrayList效能比LinkedList要好,大部分時候都考慮使用ArrayList。

使用List集合的建議:
-如果需要遍歷,對於ArrayList、Vector集合應該使用隨機訪問方法(get);對於LinkedList則更應使用迭代器(Iterator)。
-頻繁插入、刪除則考慮使用LinkedList,使用ArrayList、Vector集合需要經常重新分配內部陣列。
-多執行緒訪問可以考慮使用Collections將集合包裝成執行緒安全的集合

注意:所有內部基於陣列的集合實現,如ArrayList、ArrayDeque等,使用隨機訪問的效能比使用Iterator迭代訪問的效能要好,因為隨機訪問會被對映稱對陣列元素的訪問

4)Map

Map包含了一個keySet()方法,用於返回Map裡所有kay組成的Set集合。

還提供了一個Entry內部類來封裝kay-value對,而計算Entry儲存時只考慮Entry封裝的key。

HashMap和Hashtable

其兩者關係完全類似於ArrayList和Vector,Hashtable不允許使用null作為key和value,HashMap不允許有key相同,所以只能有一對key-value的key為null(就像Set)。

LinkedHashMap

HashMap的子類,使用雙向連結串列來維護key-value對的次序

Properties讀寫屬性檔案

Hashtable類的子類,其key和value都只能是字串型別。相當於key、value都是String型別的Map;

SortedMap介面和TreeMap實現類,如SortedSet和treeSet一般

WeakHashMap實現類,和HashMap的用法基本相似,但是WeakHashMap的key只保留對實際物件的弱引用。

IdentityHashMap實現類

和HashMap基本相似,但是當且僅當兩個key嚴格相等(key1 == key2)時,才認為兩個key相等,對於普通的HashMap而言,只需要key通過equals()方法比較返回true,且它們的hashCode值相等即可

EnumMap實現類

在內部以陣列形式儲存,不允許null作為key,但可作為value。

一般使用HashMap,其正是為快速查詢設計的,底層其實是採用陣列來儲存key-value對,但如果需要一個總是排好序的Map時,使用TreeMap。

4,Java集合類操作

使用Iterable遍歷

Java 8為Collection的父介面Iterable介面新增了一個forEach(Consumer action)預設方法,Consumer是一個函式式介面,accept(T t)方法是該介面中唯一的抽象方法。

使用Iterator遍歷

Iterator主要用於遍歷Collection集合中的元素,Iterator物件也被稱為迭代器。其定義了4個方法:

boolean hasNext()
Object next()
void remove()
void forEachRemaining(Consumer action)

Java 8為Iterator新增的forEachRemainin(Consumer action)方法所需的Consumer引數同樣也是函式式介面。

 當使用Iterator對集合元素進行迭代時,Iterator並不是把集合元素本身傳給了迭代變數,而是把集合元素的值傳給迭代變數,所以修改迭代變數的值對集合的元素本身沒有任何影響。 並且迭代訪問時,Collectio集合裡的元素不能被改變,只有通過Iterator的remove()方法刪除上一次next()方法返回的集合元素才可以;否則會引發java.util.concurrent.ModificationException異常。

使用Predicate 操作集合

Java 8為Collection集合新增了一個removeIf(Predicate filter)方法,該方法將會批量刪除符合filter條件的所有元素,例如

collection.removeIf(ele -> ((Stirng)ele).length() < 10); //將刪除長度小於10的字串集合元素

使用Stream操作集合

Stream、IntStream、LongStream、DoubleStream等流式API,這些API代表多個支援序列和並行聚集操作的元素;

Java還為每個流式API提供了對應的Builder,可以使用對應的Builder來建立對應的流。

獨立使用Stream的步驟如下:
-使用Stream的builder()類方法建立對應的Builder。
-重複呼叫Builder的add()方法向該流中新增多個元素。
-呼叫Builder的build()方法獲取對應的Stream。
-呼叫Stream的聚集方法。

聚集方法分為

-中間方法(intermediate):中間操作允許流保持開啟狀態,可直接呼叫後續方法,中間方法返回的是另一個流;
-末端方法(terminal):末端方法是對流的最終操作,執行之後該流會被消耗,不再可用。


主要參考《瘋狂Java講義》,本人才疏學淺,如有錯誤煩請各位大佬指點


另外菜鳥的這篇教程通過介面,實現類,演算法三個層次去分析集合,寫的很不錯。Java 集合框架菜鳥教程