Collection 接口主要關注集合的添加,刪除,包含java
isEmpty
: 判斷是否沒有元素size
: 獲取元素個數add
: 添加元素addAll
: 添加給定集合中的全部元素,至關於並集remove
: 刪除元素removeAll
: 刪除給定集合中的全部元素,至關於差集removeIf
: 刪除知足謂詞的元素retainAll
: 保留給定集合中的元素,至關於交集contains
: 判斷某個元素是否在集合內containsAll
: 判斷給定集合中的全部元素是否都在集合內clear
: 清空全部元素stream
: 支持流處理{ Collection<Integer> c = new ArrayList<>(List.of(1, 2, 3, 4, 5)); assertEquals(c.size(), 5); assertFalse(c.isEmpty()); assertTrue(c.contains(3)); assertTrue(c.containsAll(List.of(2, 4))); c.clear(); assertEquals(c.size(), 0); assertTrue(c.isEmpty()); } { Collection<Integer> c = new ArrayList<>(List.of(1, 2, 3, 4, 5)); c.add(6); assertThat(c, equalTo(List.of(1, 2, 3, 4, 5, 6))); c.addAll(List.of(7, 8, 9)); assertThat(c, equalTo(List.of(1, 2, 3, 4, 5, 6, 7, 8, 9))); } { Collection<Integer> c = new ArrayList<>(List.of(1, 2, 3, 4, 5)); c.remove(3); assertThat(c, equalTo(List.of(1, 2, 4, 5))); c.removeAll(List.of(2, 3)); assertThat(c, equalTo(List.of(1, 4, 5))); c.retainAll(List.of(1, 2, 3, 4)); assertThat(c, equalTo(List.of(1, 4))); c.removeIf(x -> x % 2 == 0); assertThat(c, equalTo(List.of(1))); } { Collection<Integer> c = new ArrayList<>(List.of(1, 2, 3, 4, 5)); c.forEach(System.out::print); assertEquals(c.stream().map(x -> x * x).mapToInt(x -> x).sum(), 55); for (Integer i : c) { System.out.print(i); } }
List 接口爲順序表,繼承自 Collection,關注集合的定位,查找,修改和排序,底層有兩種實現,鏈表和數組,鏈表有較好的頭部插入性能,數組在隨機訪問的時候有很大優點,util 裏主要提供了三種順序表:git
LinkedList
: 雙鏈表實現,定位元素須要遍歷,get 性能是 O(n);插入性能 O(1),但指定下標插入須要先定位;查找也須要遍歷,性能 O(n)ArrayList
: 數組實現,插入時須要移動數組中的元素,插入性能是 O(n),向後插入是 O(1),插入時若是數組空間不夠,須要從新申請新的空間,並將原來的元素添加到新的數組中;能夠根據下標定位元素,支持隨機訪問,get 性能是 O(1);查找須要遍歷,性能 O(n)Vector
: 和 ArrayList
底層同樣,可是是線程安全的List
在 Collection
的基礎上,提供了下面接口:github
get
: 按下標定位元素indexOf
: 查找元素,返回下標lastIndexOf
: 從後向前查找元素subList
: 子鏈表set
: 指定下標修改sort
: 排序replaceAll
: 對全部元素用 UnaryOperator 的返回值替換{ List<Integer> l = new ArrayList<>(List.of(1, 2, 3, 4, 5, 4, 3, 2, 1)); assertEquals(l.get(2), Integer.valueOf(3)); assertEquals(l.indexOf(3), 2); assertEquals(l.indexOf(6), -1); assertEquals(l.lastIndexOf(3), 6); assertEquals(l.subList(2, 6), List.of(3, 4, 5, 4)); } { List<Integer> l = new ArrayList<>(List.of(1, 2, 3, 4, 5, 4, 3, 2, 1)); l.set(5, 6); assertThat(l, equalTo(List.of(1, 2, 3, 4, 5, 6, 3, 2, 1))); } { List<Integer> l = new ArrayList<>(List.of(1, 2, 3, 4, 5, 4, 3, 2, 1)); l.sort(Integer::compareTo); assertThat(l, equalTo(List.of(1, 1, 2, 2, 3, 3, 4, 4, 5))); } { List<Integer> l = new ArrayList<>(List.of(1, 2, 3, 4, 5, 4, 3, 2, 1)); l.replaceAll(x -> x * x); assertThat(l, equalTo(List.of(1, 4, 9, 16, 25, 16, 9, 4, 1))); }
Set
和 List
的本質區別在於可重複性,Set
中的元素是不可重複的,Set
又分爲有序 Set
和無序 Set
,有序 Set
中的元素是按順序排列的,util 中提供了三種實現數組
TreeSet
: 有序 Set,元素必須是可比較的,使用紅黑樹實現,插入刪除查找代價都是 O(lgn)HashSet
: 無序 Set,元素必須是能被 hash 的,使用 hash 表實現,插入刪除查找代價都是 O(1)LinkedHashSet
: 無序的 Set,可是提供能插入順序的遍歷,使用 hash + 鏈表實現,插入刪除查找都是 O(1)Set
沒有提供 Collection
接口以外的接口安全
同時 TreeSet
還實現了 SortedSet
和 NavigableSet
數據結構
SortedSet
繼承自 Set
,提供了以下接口:性能
first
: 最小的元素last
: 最大的元素headSet
: 頭部集合,小於給定元素的元素構成的集合tailSet
: 尾部集合,大於等於給定元素的元素構成的集合subSet
: 子集,[from, to) 集合SortedSet<String> set = IntStream.range(0, 10).boxed().map(x -> "key" + x).collect(Collectors.toCollection(TreeSet::new)); assertEquals(set.first(), "key0"); assertEquals(set.last(), "key9"); assertThat(set.headSet("key3"), equalTo(Set.of("key0", "key1", "key2"))); assertThat(set.tailSet("key7"), equalTo(Set.of("key7", "key8", "key9"))); assertThat(set.subSet("key3", "key7"), equalTo(Set.of("key3", "key4", "key5", "key6")));
NavigableSet
繼承自 SortedSet
,提供了以下接口:測試
lower
: 小於給定值的最大值higher
: 大於給定值的最小值floor
: 小於等於給定值中的最大值ceiling
: 大於等於給定值的最小值pollFirst
: 刪除並獲取最小值pollLast
: 刪除並獲取最大值descendingSet
: 獲取倒排的集合headSet
: 頭部集合,提供額外參數是否包含給定值tailSet
: 尾部集合,提供額外參數是否包含給定值subSet
: 子集,提供額外參數是否包含給定值{ NavigableSet<String> set = IntStream.range(0, 10).boxed().map(x -> "key" + x).collect(Collectors.toCollection(TreeSet::new)); assertEquals(set.lower("key6"), "key5"); // < assertEquals(set.higher("key6"), "key7"); // > assertEquals(set.floor("key6"), "key6"); // <= assertEquals(set.ceiling("key6"), "key6"); // >= set.remove("key6"); assertEquals(set.floor("key6"), "key5"); assertEquals(set.ceiling("key6"), "key7"); } { NavigableSet<String> set = IntStream.range(0, 5).boxed().map(x -> "key" + x).collect(Collectors.toCollection(TreeSet::new)); assertEquals(set.pollFirst(), "key0"); assertThat(set, equalTo(Set.of("key1", "key2", "key3", "key4"))); assertEquals(set.pollLast(), "key4"); assertThat(set, equalTo(Set.of("key1", "key2", "key3"))); } { NavigableSet<String> set = IntStream.range(0, 10).boxed().map(x -> "key" + x).collect(Collectors.toCollection(TreeSet::new)); assertThat(set.descendingSet(), equalTo(Set.of("key9", "key8", "key7", "key6", "key5", "key4", "key3", "key2", "key1", "key0"))); assertThat(set.headSet("key3", false), equalTo(Set.of("key0", "key1", "key2"))); assertThat(set.tailSet("key7", true), equalTo(Set.of("key7", "key8", "key9"))); assertThat(set.subSet("key3", true, "key7", false), equalTo(Set.of("key3", "key4", "key5", "key6"))); }
Queue
隊列(先進先出),繼承自 Collection
,關注集合的有序性,支持尾部插入,頭部刪除,以及頭部元素的獲取,util 提供了三種 Queue
spa
LinkedList
: LinkedList 實現了 Queue 的接口,元素按插入順序排列ArrayDeque
: 數組實現的 Queue,元素按插入順序排列PriorityQueue
: 優先隊列,堆實現,元素按從小到大排列Queue
在 Collection
基礎上提供了以下接口:線程
add
: 添加元素,若是隊列滿了,拋出異常remove
: 刪除元素,若是隊列爲空,拋出異常element
: 獲取頭部元素,若是隊列爲空,拋出異常offer
: 添加元素,若是隊列滿了,返回 falsepoll
: 刪除元素,若是隊列爲空,返回 nullpeek
: 獲取頭部元素,若是隊列爲空,返回 null{ Queue<Integer> queue = new LinkedList<>(); // add / remove / element assertThrows(NoSuchElementException.class, queue::remove); assertThrows(NoSuchElementException.class, queue::element); IntStream.range(0, 10).forEach(queue::add); assertThat(queue.toArray(), equalTo(new Integer[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); assertEquals(queue.element(), Integer.valueOf(0)); assertEquals(queue.remove(), Integer.valueOf(0)); } { Queue<Integer> queue = new LinkedList<>(); // offer / poll / peek assertEquals(queue.poll(), null); assertEquals(queue.peek(), null); IntStream.range(0, 10).forEach(queue::offer); assertThat(queue.toArray(), equalTo(new Integer[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); assertEquals(queue.peek(), Integer.valueOf(0)); assertEquals(queue.poll(), Integer.valueOf(0)); }
Deque
雙端隊列,繼承自 Queue
,關注集合的兩端的插入和刪除以及兩端元素的獲取,util 提供了兩種 Deque
LinkedList
: 鏈表實現的 Deque
ArrayDeque
: 數組實現的 Deque
Deque
在 Queue
的基礎上提供了下面接口:
addFirst
: 頭部插入,隊列滿,拋異常addLast
: 尾部插入,隊列滿,拋異常removeFirst
: 頭部刪除,隊列空,拋異常removeLast
: 尾部刪除,隊列空,拋異常getFirst
: 獲取頭部元素,隊列空,拋異常getLast
: 獲取尾部元素,隊列空,拋異常offerFirst
: 頭部插入,隊列滿,返回 falseofferLast
: 尾部插入,隊列滿,返回 falsepollFirst
: 頭部刪除,隊列空,返回 nullpollLast
: 尾部刪除,隊列空,返回 nullpeekFirst
: 獲取頭部,隊列空,返回 nullpeekLast
: 獲取尾部,隊列空,返回 nullpush
: 做爲 Stack
使用,插入元素(頭部插入),隊列滿,拋異常pop
: 做爲 Stack
使用,刪除元素(頭部刪除),隊列空,拋異常removeFirstOccurrence
: 刪除第一個與給定值相等的對象,返回是否有元素刪除removeLastOccurrence
: 刪除最後一個與給定值相等的對象,返回是否有元素刪除{ Deque<Integer> deque = new ArrayDeque<>(); assertThrows(NoSuchElementException.class, deque::getFirst); assertThrows(NoSuchElementException.class, deque::getLast); assertThrows(NoSuchElementException.class, deque::removeFirst); assertThrows(NoSuchElementException.class, deque::removeLast); IntStream.range(0, 5).forEach(deque::addFirst); IntStream.range(5, 10).forEach(deque::addLast); assertThat(deque.toArray(), equalTo(new Integer[]{4, 3, 2, 1, 0, 5, 6, 7, 8, 9})); assertEquals(deque.getFirst(), Integer.valueOf(4)); assertEquals(deque.getLast(), Integer.valueOf(9)); assertEquals(deque.removeFirst(), Integer.valueOf(4)); assertEquals(deque.removeLast(), Integer.valueOf(9)); } { Deque<Integer> deque = new ArrayDeque<>(); assertEquals(deque.peekFirst(), null); assertEquals(deque.peekLast(), null); assertEquals(deque.pollFirst(), null); assertEquals(deque.pollLast(), null); IntStream.range(0, 5).forEach(deque::offerFirst); IntStream.range(5, 10).forEach(deque::offerLast); assertThat(deque.toArray(), equalTo(new Integer[]{4, 3, 2, 1, 0, 5, 6, 7, 8, 9})); assertEquals(deque.peekFirst(), Integer.valueOf(4)); assertEquals(deque.peekLast(), Integer.valueOf(9)); assertEquals(deque.pollFirst(), Integer.valueOf(4)); assertEquals(deque.pollLast(), Integer.valueOf(9)); } { Deque<Integer> deque = new ArrayDeque<>(); IntStream.range(0, 10).forEach(deque::push); assertThat(deque.toArray(), equalTo(new Integer[]{9, 8, 7, 6, 5, 4, 3, 2, 1, 0})); assertEquals(deque.element(), Integer.valueOf(9)); assertEquals(deque.pop(), Integer.valueOf(9)); } { Deque<Integer> deque = new ArrayDeque<>(); IntStream.range(0, 10).forEach(deque::push); assertTrue(deque.removeFirstOccurrence(2)); assertTrue(deque.removeLastOccurrence(8)); assertThat(deque.toArray(), equalTo(new Integer[]{9, 7, 6, 5, 4, 3, 1, 0})); }
和 Queue
的先進先出不一樣,Stack
是一種表明後進先出的數據結構,util 中並無提供 Stack
接口,事實上 Deque
中已經包含了 Stack
接口,所以當你須要一個 Stack
的時候,能夠構造一個 Deque
,java doc 也是這麼建議的
此外,util 中還有一個 Stack
類,繼承自 Vector
,線程安全,這個類的設計和定位比較尷尬,不建議使用
Collection
測試代碼: https://github.com/hatlonely/... List
測試代碼: https://github.com/hatlonely/... Set
測試代碼: https://github.com/hatlonely/... Queue
測試代碼: https://github.com/hatlonely/... Deque
測試代碼: https://github.com/hatlonely/...