置頂 0%

高頻率出現的Java Collections

前言

最近在Leetcode刷個幾題,使用到集合(Collection)物件的頻率甚高,顧名思義就是把多個有關聯的資料存放在Collection裡面,而這些資料叫做元素(Elements),同時也就是物件。因為常常會不小心忘記有一些集合的宣告方法或具有哪些方法,因此,這邊來記錄一下我在Leetcode上最常用到的幾個Collection。

Collection

集合物件(Collections)是將一群相關的資料聚集在一個物件當中,且可以對這些資料做存放及排序等操作,其實就類似陣列,所以Collection也被人叫做動態陣列(dynamically array),最重要的是它具備許多有效和方便的功能。下列為Collection的特色

  • 屬於Java的java.util.*套件
  • 在集合裡面的成員(Element)要是物件(Object)型態,如果要使用基本型別的話要用Wrapper class(但其實存放int宣告的變數還是可以,Java會幫你轉成Integer)
  • 可以搭配使用到泛型(genric),讓編譯時就可以檢查元素的資料型態,所以會具有更彈性的型別安全(type safety)檢查機制,且同時可以減少轉型(Casting)的使用
  • 實作Collection的物件有許多都是常見的資料結構

下面這張圖是集合物件之間的關係圖

Stack

堆疊(Stack)繼承Vector類別,實現了一種資料結構為後進先出(LIFO)的類別。因為Stack繼承父類別Vector的的add(Element e)及isEmpty()等方法,但使用Stack類別自己實作的push(Element e)及empty()方法可以增加程式的可讀性及目的性 (引用link )。

1
2
3
4
5
6
7
8
9
10
11
12
Stack<Integer> stack = new Stack<Integer>();
stack.push(10);
stack.push(null); //stack可以存放null
stack.push(5);
stack.push(1);
System.out.println(stack); //[10, null, 5, 1]
System.out.println(stack.size()); //4
System.out.println(stack.indexOf(1)); //3
System.out.println(stack.peek()); //1,檢視為上層的物件(不移除)
int t = stack.pop(); //移除Stack中的最上層的物件,並返回此物件,所以t=1
System.out.println(stack); //[10, null, 5]
System.out.println(stack.search(10)); //3,search為返回目標物件在stack中到最上層的物件的距離,如果最上層是5,stack.search(5)就會返回1

另外還要注意當stack為空時,如果使用peek()和pop()會拋出java.util.EmptyStackException

1
2
3
4
5
6
7
Stack<Integer> stack = new Stack<Integer>();
try {
stack.peek();
stack.pop();
} catch (EmptyStackException e) {
System.out.println("Stack為空");
}

Queue

貯列(Queue)與Stack相反,資料型態為先進先出(FIFO)的類別,這邊要注意的地方是Queue為一個介面,要由LinkedList或PriorityQueue來實作,還有Queue因為繼承至Collection介面,所以也具備一些相同的等方法,但通常為了可讀性及安全性,還是會使用Queue自己的offer()及poll()等方法,而且官方文件有提到offer()、poll()和peek()遇到操作失敗時,不同於add()、remove()及element()會直接拋出Exception,反而是會返回特定值,像是offer()會返回boolean值 ; poll()遇queue為空,則是會回傳null,否則就回傳最前面的那個物件,並再回傳後刪除此物件 ; peek()也是當queue為空時,即返回一個null,不然就回傳queue最前面那一個物件。Queue有自己的一個不放參數直接remove()方法,其表示移除最接近的元素,但要小心,如果遇到空的Queue,則會拋出java.util.NoSuchElementException

LinkedList PriorityQueue
最常見實作Queue的類別,具備貯列(Queue)基本的原則(FIFO),規則為每次都從尾端加入,並從前端來取出元素,來達到類似排隊的效果 從行為來看PriorityQueue已經沒有貯列(Queue)基本的原則(FIFO),因為他的排列順序是根據元素的小到大,意思就是每次取出(poll)的元素都是Queue中數值為小的那一個
可存放null元素 不能存放null元素,會拋出java.lang.NullPointerException
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Queue<Integer> queue = new LinkedList<Integer>();
queue.offer(1);
queue.offer(5);
queue.offer(3);
queue.offer(2);
System.out.println(queue); //[1, 5, 3, 2]
System.out.println(queue.poll()); //1
System.out.println(queue); //[5, 3, 2]
System.out.println(queue.peek()); //5

Queue<Integer> queue = new PriorityQueue();
queue.offer(1);
queue.offer(5);
queue.offer(3);
queue.offer(2);
System.out.println(queue); //[1, 2, 3, 5]
System.out.println(queue.poll()); //1
System.out.println(queue); //[2, 5, 3]
System.out.println(queue.peek()); //2

Dequeue

1
Deque deque = new ArrayDeque();

通用方法

Iterable 介面

方法 說明 回傳型態
hasNext() 判斷迭代器還有沒有元素,有的話就回傳true boolean
next() 將迭代器的元素傳回,並指向下一個元素,只能從前往後取值(不可逆) Object()
remove() 刪除iterator.next()方法目前指到的元素,所以可以在迴圈裏面放在next()的後面,就可以清空集合物件的元素了 void
1
2
3
4
5
6
7
8
9
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
//System.out.println(iterator.next()); // 跳出java.util.NoSuchElementException

Collection 介面

方法 說明 回傳型態
remove(Object o)
刪除放在參數的o物件,成功回傳true boolean
remove(int i) 移除索引值為i的物件,成功則回傳此物件,若超出集合物件的索引時會拋出java.lang.IndexOutOfBoundsException 泛型所宣告的物件型態<E>
indexOf(Object o) 指參數的物件在集合物件從前面數來第幾個索引(從0開始),而還有一個是lastIndexOf(Object o)則是從後面來找尋,若都沒有符合的那一個物件就回傳一個-1,注意這是具有索引的集合物件才有的方法,像是Set或Map就沒有 int
size() 回傳集合的元素有多少個元素 int
iterator() 將Collection變成iterator物件,以便來取得集合內所有的值,通常會搭配一個迴圈,然後條件判斷呼叫已經iterator()的參考變數的hasNext(),來判斷是否還有元素可以迭代出來,迴圈裡面使用參考變數的next()來取集合內的值 Iterator
isEmpty() 檢視集合物件是否為空 boolean