集合

      在〈集合〉中尚無留言

集合(Collections)

以往要將原生資料或物件放入陣列中,陣列的長度需先宣告,一宣告就不能變更長度。若事先不知道長度或者要隨時可以變更長度,就必需使用集合。可以把集合想成是多啦A夢的百寶袋,要裝多少物件都可以,只要記憶体足夠即可。

集合中的每個物件被稱為元素(elements),每個元素的型態可以不一樣,因為都會被轉換成 Object (未使用泛型時),不過原生資料不允許被在集合之中

集合的重點在於如何新增移除元素,如何找到並取出元件,以及走訪整個集合。集合重度依靠泛型而寫成的,所以就不再限定只會轉成 Object 。

Collection Type

集合的類型如下圖所示

collectionhierarchy

Map Type

Map 的類型如下圖所示

maparchitecture

Collection 介面有三個子類別,分別是 LIst,Queue 及 Set。

Map 是另一個獨立的介面,跟 Collection 無關,它類似 Python 的字典。Collection 介面定義了add,addAll,clear,contains,wquals,remove,removeAll,size,iterator 等相關方法。

Iterator 介面

Iterator 為 Collection 的走訪器,有hasNext(),next(),remove() 等方法,只能由上往下走。若要能往上讀取就要使用ListIterator。

ListIterator 繼承 Iterator,可作新增修改刪除動作,每個元素間都有 index,可用 index 取得元素,有 add,hasNext,hasPrevious,next,nextIndex,previous,previousIndex,remove,set 等方法。

Enumeration 介面

為 Map 的走訪器,有 hasMoreElements,nextElement 等方法。

集合的四特性

了解每一個集合時, 需記住每個集合是否有如下四個特性 :

排序性 : 遞增或遞減的特性。
順序性 : 是否有依加入的順序排列。有順序就無排序, 有排序就無順序。
重複性 : 是否允許出現重複的物件。
鍵值 (Key/value) : 使用鍵值存放物件,只有 Map 使用此法。

集合介面 排序性 順序性 不允許重複 使用鍵值
ArrayList   v    
LinkedList   v    
Vector   v    
HashSet     v  
LinkedHashSet   v v  
TreeSet v   v  
HaspMap       v
LinkedHashMap   v   v
HashTable       v
TreeMap v     v

List 介面

最像陣列的集合,每個集合都有 index,除了可動態擴充長度外,其他都跟陣列一樣。

所有的 List 都是有順序性、無排序、可重複,可使用如下的方法新增、插入、刪除

add("Apple") //在最後新增資料
add(2,"Banana") //在索引2 插入新資料
get(index) //取得 index 索引的資料
remove(index) //移除 index 索引的資料
indexOf("Apple") //取得第一個 "Apple 的索引編號

ArrayList

最簡易使用的 List 就屬 ArrayList,使用 add 新增、get(index) 取出、remove(index) 刪除。ArrayList 底層其實是一個陣列,並不是雙向連結。當元素超出目前陣列容量時,ArrayList 會自動擴充容量(通常是原來容量的 1.5 倍到 2 倍),並複制資料到新的陣列中,在效能上其實還不錯。

非泛型ArrayList

🔒 底下內容僅限會員閱讀。

立即登入

非泛型會產生 Runtime error,且必需要強制轉型。泛型會產生 Compiler error,不需強制轉型。

初始化

new ArrayList<>() 是產生一個空的 List,如果要給定初始值,可以使用如下二種方式。

傳入 List.of()。List.of() 是不可變更的 List,但加上 new ArrayList 後,此 List 即可變更。

Listages=new ArrayList<>(List.of(10,20,30,40,50));

另也傳入 Array.asList()

Listages=new ArrayList<>(Arrays.asList(10,20,30,40,50));

LinkedList

LinkedList 採用雙向鏈結,所以在新增刪除的效能比 ArrayList 快很多,但走訪的效能比 ArrayList 差。LinkedList 比 ArrayList 多了一個 addLast,其功能同 add。

排序

如果要排序的資料是 Integer、String 等簡易的資料型態,可以使用 List 裏的 sort、Collection.sort 及 stream 的三種方式排序,如下代碼所示。

🔒 底下內容僅限會員閱讀。

立即登入

如果要排序的資料是自訂資料結構,也有如下二種方式。

🔒 底下內容僅限會員閱讀。

立即登入

Vector

Vector 是最原始的集合,特性同 ArrayList。但 Vector 是 Thread-safe,效能遠比 ArrayList 差,建議能不要用就不用。

Stack

繼承 Vector,具後進先出原則,使用 push 加入,pop 取出(並刪除),peek取出(但不刪除)。

Set 介面

Set 介面的特性為裏面的物件不會重複

HastSet

HastSet 使用 HashCode 來判斷物件是否相同,如果相同則新物件會覆蓋舊物件,所以 HashSet 裏的物件不會重複,且無順序性,無排序性。

HashCode (雜湊碼) 是一種數學演算法,HashSet 使用 HashCode 決定物件要存放的位置。所以在大量的資料中要查找某個物件,使用 HashSet 是個效能非常高的方式。

🔒 底下內容僅限會員閱讀。

立即登入

LinkedHashSet

LinkedHashSet 也是使用 HashCode 決定物件存放的位置,但多了雙向連結記錄上下物件,所以具順序性,無排序,不允許重複,新增修改的效能略遜於 HashSet (因為要加雙向連結)。

🔒 底下內容僅限會員閱讀。

立即登入

若要將 HashSet 依加入的順序取出的話,可轉為 LinkedHashSet 類型,如下所示。

HashSet hs=new HashSet();
LinkedHashSet lhs=new LinkedHashSet(hs);

TreeSet

TreeSet 不是使用 HashCode 來判斷物件是否重覆,它是繼承 SortedSet,使用二元樹排序,一樣重複的物件會覆蓋舊物件,具排序性,無順序性,不可重複,新增修改的效能是最差的。

Queue 介面

Queue 具先進先出原則,但不要使用 add、remove 方法,因為會丟出例外。需改採 offer、poll、peek 三個方法。

LinkedList

LinkedList 除了實作 List 介面外,還實作了 Queue 介面,所以 LinkedList 除了可以當作 List 來使用,也可以當成 Queue。

Queue q=new LinkedList();
q.offer("First");
q.poll();

PriorityQueue

是一個可以自訂排序方式的類別,排序時先實作 Comparator 裏的 compare()方法,再將產生的物件放入PriorityQueue 建構子。

🔒 底下內容僅限會員閱讀。

立即登入

注意, String s=”abcd”;
s.compare(“defg”); 先一個字一個字比, 若前面比較小, 傳回負數, 前面比較大, 傳回正數, 二個都一樣, 傳回 0

Iterator

 for-each 遍訪所有元素比較簡潔,但無法在迴圈中刪除資料,否則會發生 ConcurrentModificationException 例外。

使用 Iterator 遍訪所有元素時,可以在迴圈中安全的刪除修改元素,比較適合邊走邊修改的需求

🔒 底下內容僅限會員閱讀。

立即登入

Map 介面

Map在其他的語言如Python, C#中, 稱為字典, 是一個包含key及value的袋子. key必需是唯一, 值為物件. Map不繼承Collection介面. 使用put/putAll加入元素, get(key)取回元素

HashMap

無順序, 無排序, 可允許key及value都是null

LinkedHashMap

同HashMap, 但因為加了雙向鏈結, 所以走訪效能快, 新增刪除效能差

HashTable

同HashMap, 但這是thread-safe的, 鍵值不可為null

SortedMap

根據key值作自然排序, key不得重複也不可能null

TreeMap

實作SortedMap, 採二元樹排序, 裏面的鍵值必需是同一種資料型態

🔒 底下內容僅限會員閱讀。

立即登入

Deque 介面

Deque是Collection的子介面, 可同時作為queue及stack
queue : FIFO, add, remove
stack : LIFO, push, pop

  Deque stack=new ArrayDeque<>();
  stack.push("one");
  stack.push("two");

Collections集合工具

Collections.synchronizedMap(map) : 變成thread-safe
Collections.sort(list, sort); 依sort方式來排序, 見下面說明

排序集合(Ordering Collections)

Comparable 介面 : 需實作compareTo(), 僅提供一個排序的方式
返回值需包含0, 1, -1三個, 加入Collection的物件, 會依此排序取出

Comparator介面 : 需實作compare(), 可建立多個排序方式
List<Student> list=new ArrayList<>();
Compartor<Student> sortName=new StudentSortName();
Comparator<Student>sortGpa=new StudentSortGpa();
Colloections.sort(list, sortName); <==依sortName排序
Colloections.sort(list, sortGpa); <==依sortGpa序

NavigableSet/NavigableMap

此二個會根據內容作自然排序

NavigableSet 為SortedSet, 只可用在TreeSet;
NavigableSet<Integer> ns1=new TreeSet<>();

NavigableMap為SortedMap, 只可用在TreeMap;
NavigableMap<Integer, Integer> ns2=new TreeMap<>();

並行集合

常見的有
ConcurrentHashMap : 同步HashMap實作
ConcurrentSkipListMap : 同步TreeMap實作
CopyOnWriteArrayList : 同步ArrayList實作

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *