博主:_LJaXi Or 東方幻想郷
專欄: Java | 從跨行業到跨平臺
開發工具:IntelliJ IDEA 2021.1.3
Java集合框架 API接口
- Collection接口
- List接口
- HashSet, TreeSet
- Set接口
- `使用 HashSet 實現`
- `使用 TreeSet 實現`
- HashMap、TreeMap
- Map接口
- `使用 HashMap 實現`
- `使用 TreeMap 實現`
- LinkedList、PriorityQueue
- Queue接口
- `使用 LinkedList 實現`
- `使用 PriorityQueue 實現`
- ArrayDeque、LinkedList
- Deque接口
- `使用 ArrayDeque 實現`
- `使用 LinkedList 實現`
- Java 集合框架那么多接口,功能都相似,我該如何區分使用?
Java集合API提供了一組功能強大的數據結構和算法, 具有以下作用(
簡述
)
存儲和組織數據
提供高效的數據訪問和操作
實現算法和數據處理
提供線程安全性
支持泛型編程
java.util.Collection
是集合框架的根接口。它位于集合框架層次結構的頂部。它包含一些重要的方法,例如每個Collection
類都必須實現的size()、iterator()、add()、remove()、clear()
其他一些重要的接口是java.util.List、java.util.Set、java.util.Queue、java.util.Map
,Map
是唯一不繼承自Collection
接口的接口,但它是Collections
框架的一部分。所有集合框架接口都存在于java.util
包中
Collection接口
代表了一組對象的集合。它是其他集合接口的父接口,提供了基本的操作方法,如添加、刪除、查詢等。
Collection<String> collection = new ArrayList<>();// 添加元素
collection.add("元素1");
collection.add("元素2");
collection.add("元素3");// 刪除元素
collection.remove("元素2");// 遍歷集合
for (String item : collection) {System.out.println(item);
}
List接口
繼承自
Collection
接口,表示有序的集合。List中的元素可以根據索引進行訪問,可以包含重復的元素。
import java.util.ArrayList;
import java.util.List;public class ListExample {public static void main(String[] args) {List<String> list = new ArrayList<>();// 添加元素list.add("Java");list.add("Python");list.add("C++");// 獲取元素String element = list.get(0);System.out.println("第一個元素:" + element);// 刪除元素list.remove(1);// 遍歷元素for (String str : list) {System.out.println(str);}// 判斷是否包含某個元素boolean contains = list.contains("Java");System.out.println("是否包含Java:" + contains);// 清空列表list.clear();// 判斷列表是否為空boolean empty = list.isEmpty();System.out.println("列表是否為空:" + empty);}
}
HashSet, TreeSet
HashSet
是 Java 集合框架中Set
接口的實現類之一,它是一個無序、不重復的集合
TreeSet
是 Java 集合框架中 Set 接口的另一個實現類,它基于紅黑樹的數據結構實現,TreeSet 的作用是提供了一個有序且不重復的集合
Set接口
繼承自
Collection
接口,表示不允許包含重復元素的集合。Set沒有定義特定的順序,可以使用HashSet、TreeSet等具體實現。
使用 HashSet 實現
import java.util.Set;
import java.util.HashSet;public class SetExample {public static void main(String[] args) {// 創建HashSet對象Set<String> set = new HashSet<>();// 添加元素set.add("Apple");set.add("Banana");set.add("Orange");set.add("Grape");// 打印集合大小System.out.println("集合大小: " + set.size());// 遍歷集合for (String fruit : set) {System.out.println(fruit);}// 判斷集合中是否包含指定元素String target = "Banana";if (set.contains(target)) {System.out.println("集合中包含" + target);} else {System.out.println("集合中不包含" + target);}// 刪除元素set.remove("Orange");// 清空集合set.clear();// 判斷集合是否為空if (set.isEmpty()) {System.out.println("集合為空");} else {System.out.println("集合不為空");}}
}
使用 TreeSet 實現
import java.util.Set;
import java.util.TreeSet;public class TreeSetExample {public static void main(String[] args) {Set<Integer> set = new TreeSet<>();// 添加元素set.add(5);set.add(2);set.add(8);set.add(3);set.add(1);// 遍歷集合for (Integer element : set) {System.out.println(element);}// 獲取集合大小int size = set.size();System.out.println("集合大小: " + size);// 判斷集合中是否包含指定元素boolean contains = set.contains(3);System.out.println("集合中是否包含3: " + contains);// 刪除元素set.remove(2);// 判斷集合是否為空boolean isEmpty = set.isEmpty();System.out.println("集合是否為空: " + isEmpty);}
}
HashMap、TreeMap
HashMap
是基于哈希表實現的,它提供了快速的插入、刪除和查找操作,時間復雜度為O(1)
HashMap
不保證順序,允許有null鍵
和null值
,適用于大多數情況,特別是在需要快速查找鍵值對的場景中
O(1)
就是不需要遍歷查找,直接得到搜索結果的,例如哈希表、bitmap等數據結構,都可以作為O(1)
時間復雜度算法的數據結構
TreeMap
是基于紅黑樹(一種自平衡二叉搜索樹)實現的,它可以保持元素的有序性,TreeMap
支持高效的插入、刪除和查找操作,時間復雜度為O(logN)
O(logN)
是一種時間復雜度的表示,表示算法在最壞情況下的運行時間與輸入規模N
的對數成正比。其中,O 表示“大約”
,而logN 是以 2
為底的對數
Map接口
表示鍵值對的映射集合。Map中的元素以鍵值對的形式存儲,通過鍵來唯一標識值。常用的實現類有HashMap、TreeMap等。
使用 HashMap 實現
import java.util.HashMap;
import java.util.Map;public class HashMapWithNulls {public static void main(String[] args) {// 創建一個 HashMap 實例,允許 null 鍵和 null 值Map<String, Integer> map = new HashMap<>();// 添加鍵值對,包括 null 鍵和 null 值map.put("key1", 100);map.put(null, 200);map.put("key3", null);// 獲取鍵對應的值,包括 null 鍵和 null 值Integer value1 = map.get("key1");System.out.println("key1 對應的值: " + value1);Integer value2 = map.get(null);System.out.println("null 對應的值: " + value2);Integer value3 = map.get("key3");System.out.println("key3 對應的值: " + value3);// 遍歷所有的鍵值對,包括 null 鍵和 null 值for (Map.Entry<String, Integer> entry : map.entrySet()) {String key = entry.getKey();Integer value = entry.getValue();System.out.println("鍵: " + key + ", 值: " + value);}// 刪除特定的鍵值對map.remove(null);// 判斷是否包含某個鍵boolean containsKey = map.containsKey(null);System.out.println("是否包含 null 鍵: " + containsKey);// 判斷是否包含某個值boolean containsValue = map.containsValue(null);System.out.println("是否包含 null 值: " + containsValue);// 判斷集合是否為空boolean isEmpty = map.isEmpty();System.out.println("集合是否為空: " + isEmpty);}
}
使用 TreeMap 實現
import java.util.Map;
import java.util.TreeMap;public class TreeMapExample {public static void main(String[] args) {// 創建一個 TreeMap 實例TreeMap<String, Integer> treeMap = new TreeMap<>();// 添加鍵值對treeMap.put("Alice", 95);treeMap.put("Bob", 87);treeMap.put("Charlie", 92);treeMap.put("David", 78);// 獲取鍵對應的值int aliceScore = treeMap.get("Alice");System.out.println("Alice 的分數是:" + aliceScore);// 遍歷所有的鍵值對for (Map.Entry<String, Integer> entry : treeMap.entrySet()) {String name = entry.getKey();int score = entry.getValue();System.out.println(name + " 的分數是:" + score);}// 獲取第一個鍵值對Map.Entry<String, Integer> firstEntry = treeMap.firstEntry();System.out.println("第一個鍵值對:" + firstEntry.getKey() + " => " + firstEntry.getValue());// 獲取最后一個鍵值對Map.Entry<String, Integer> lastEntry = treeMap.lastEntry();System.out.println("最后一個鍵值對:" + lastEntry.getKey() + " => " + lastEntry.getValue());// 獲取鍵小于等于給定鍵的鍵值對Map.Entry<String, Integer> floorEntry = treeMap.floorEntry("Charlie");System.out.println("小于等于 Charlie 的鍵值對:" + floorEntry.getKey() + " => " + floorEntry.getValue());// 刪除鍵值對treeMap.remove("Charlie");// 判斷集合是否為空boolean isEmpty = treeMap.isEmpty();System.out.println("集合是否為空:" + isEmpty);}
}
LinkedList、PriorityQueue
LinkedList
是 Java 集合框架中的一種實現了 List 接口的雙向鏈表數據結構。它提供了對元素的高效插入、刪除以及隨機訪問操作
LinkedList
主要適用于需要頻繁插入、刪除操作,以及在集合中間進行操作的場景,它在實現隊列、鏈表特有操作和特定的業務需求上表現出色。但需要注意在需要隨機訪問元素時,可能會使用較低的性能
PriorityQueue
主要適用于需要根據優先級對元素進行排序的場景,它在任務調度、事件排序、貪心算法等方面提供了便利,并且可以作為一種有效的搜索算法工具
Queue接口
繼承自
Collection
接口,表示隊列集合。Queue是一種特殊的集合,按照先進先出(FIFO)的方式管理元素。常用的實現類有LinkedList、PriorityQueue等。
使用 LinkedList 實現
import java.util.Queue;
import java.util.LinkedList;public class QueueExample {public static void main(String[] args) {// 創建一個隊列Queue<Integer> queue = new LinkedList<>();// 向隊列中添加元素queue.offer(1);queue.offer(2);queue.offer(3);// 獲取隊列的大小System.out.println("隊列大小: " + queue.size());// 檢查隊列是否為空System.out.println("隊列是否為空: " + queue.isEmpty());// 訪問隊列頭部的元素System.out.println("隊列頭部的元素: " + queue.peek());// 從隊列中移除元素int removedElement = queue.poll();System.out.println("從隊列中移除的元素: " + removedElement);// 遍歷隊列中的元素System.out.println("遍歷隊列中的元素:");for (int element : queue) {System.out.println(element);}}
}
使用 PriorityQueue 實現
import java.util.Queue;
import java.util.PriorityQueue;public class QueueExample {public static void main(String[] args) {// 創建一個優先級隊列Queue<Integer> queue = new PriorityQueue<>();// 添加元素到隊列queue.offer(5);queue.offer(2);queue.offer(8);queue.offer(1);// 獲取并移除隊列的頭部元素int firstElement = queue.poll();System.out.println("從隊列頭部移除的元素: " + firstElement);// 獲取隊列的頭部元素(不移除)int peekElement = queue.peek();System.out.println("隊列頭部的元素: " + peekElement);// 遍歷隊列中的元素System.out.println("遍歷隊列中的元素:");for (int element : queue) {System.out.println(element);}}
}
ArrayDeque、LinkedList
ArrayDeque
基于數組實現,它有固定的容量(默認情況下為16),但可以動態調整大小
ArrayDeque
支持高效的隨機訪問,因為它基于數組,可以通過索引快速訪問元素
ArrayDeque
在操作兩端的元素(隊列頭和隊列尾)時,具有高效的時間復雜度(O(1))
適用場景:
當你需要在隊列的兩端頻繁地插入和刪除元素時,例如實現棧、雙向隊列或循環隊列等數據結構
LinkedList
基于雙向鏈表實現,每個元素都包含前一個和后一個元素的引用
LinkedList
沒有固定的容量限制,它可以根據需要動態調整大小
LinkedList
在插入和刪除操作方面表現出色,特別是對于任意位置的元素操作
LinkedList
的隨機訪問效率較低,因為它需要遍歷鏈表來到達目標位置
適用場景:
當你需要頻繁地在任意位置插入和刪除元素時,例如實現隊列、棧、優先隊列或循環緩沖區等數據結構
Deque接口
繼承自
Queue
接口,表示雙端隊列集合。Deque支持在兩端插入、刪除元素,可以作為棧或隊列使用。常用的實現類有ArrayDeque、LinkedList等。
使用 ArrayDeque 實現
import java.util.Deque;
import java.util.ArrayDeque;public class DequeExample {public static void main(String[] args) {// 創建一個雙端隊列Deque<Integer> deque = new ArrayDeque<>();// 向隊列頭部添加元素deque.offerFirst(1);deque.offerFirst(2);deque.offerFirst(3);// 向隊列尾部添加元素deque.offerLast(4);deque.offerLast(5);// 從隊列頭部獲取元素并移除int firstElement = deque.pollFirst();System.out.println("從隊列頭部移除的元素: " + firstElement);// 從隊列尾部獲取元素并移除int lastElement = deque.pollLast();System.out.println("從隊列尾部移除的元素: " + lastElement);// 獲取隊列頭部元素但不移除int peekFirstElement = deque.peekFirst();System.out.println("隊列頭部的元素: " + peekFirstElement);// 獲取隊列尾部元素但不移除int peekLastElement = deque.peekLast();System.out.println("隊列尾部的元素: " + peekLastElement);// 遍歷隊列中的元素System.out.println("遍歷隊列中的元素:");for (int element : deque) {System.out.println(element);}}
}
使用 LinkedList 實現
import java.util.Deque;
import java.util.LinkedList;public class DequeExample {public static void main(String[] args) {// 創建一個雙端隊列Deque<Integer> deque = new LinkedList<>();// 添加元素到隊列的頭部和尾部deque.offerFirst(1);deque.offerLast(2);deque.offerFirst(3);deque.offerLast(4);// 獲取并移除隊列的頭部和尾部元素int firstElement = deque.pollFirst();int lastElement = deque.pollLast();System.out.println("從隊列頭部移除的元素: " + firstElement);System.out.println("從隊列尾部移除的元素: " + lastElement);// 獲取隊列的頭部和尾部元素(不移除)int peekFirstElement = deque.peekFirst();int peekLastElement = deque.peekLast();System.out.println("隊列頭部的元素: " + peekFirstElement);System.out.println("隊列尾部的元素: " + peekLastElement);// 遍歷隊列中的元素System.out.println("遍歷隊列中的元素:");for (int element : deque) {System.out.println(element);}}
}
Java 集合框架那么多接口,功能都相似,我該如何區分使用?
List 接口
特點:
有序集合,允許重復元素
典型實現類:
ArrayList、LinkedList
適用場景:
需要按照插入順序進行訪問和操作的場景,也可快速隨機訪問元素
Set 接口
特點:
無序集合,不允許重復元素
典型實現類:
HashSet、TreeSet
適用場景:
需要存儲不重復元素的場景,例如去重、判斷元素是否存在等
Queue 接口
特點:
先進先出(FIFO)隊列
典型實現類:
LinkedList、PriorityQueue
適用場景:
實現隊列數據結構,通常用于任務調度、事件處理等
Map 接口
特點:
鍵值對的映射
典型實現類:
HashMap、TreeMap
適用場景:
需要根據唯一鍵快速查找值的場景,如存儲關聯數據、緩存等