集合框架
主要思路是讓介面與實現分離
集合框架的介面:兩個基本介面 Collection
和 Map
集合框架的類:
介面
兩個基本介面:Collection
和 Map
Collection
以下是Collection
介面內的一些方法
public abstract interface class java.util.Collection
{
public abstract boolean add(java.lang.Object);
public abstract boolean remove(java.lang.Object);
public abstract boolean equals(java.lang.Object);
public abstract void clear();
public abstract boolean isEmpty();
public abstract boolean contains(java.lang.Object);
public abstract int size();
public abstract java.util.Iterator iterator();
public abstract boolean addAll(java.util.Collection);
public abstract boolean containsAll(java.util.Collection);
public abstract boolean removeAll(java.util.Collection);
public abstract boolean retainAll(java.util.Collection);
public boolean removeIf(java.util.function.Predicate);
...
}
複製程式碼
可以看出來就是 大小,加,刪,是否含某個元素,是否空 等等,這些集合最基礎的功能
Collection
中有Iterator
介面
public abstract interface class java.util.Iterator
{
public void remove();
public abstract boolean hasNext();
public abstract java.lang.Object next();
public void forEachRemaining(java.util.function.Consumer);
}
複製程式碼
Map
以下是Map
介面內的一些方法
public abstract interface class java.util.Map
{
public boolean remove(java.lang.Object, java.lang.Object);
public abstract java.lang.Object get(java.lang.Object);
public abstract java.lang.Object put(java.lang.Object, java.lang.Object);
public abstract boolean equals(java.lang.Object);
public abstract void clear();
public abstract boolean isEmpty();
public boolean replace(java.lang.Object, java.lang.Object, java.lang.Object);
public void replaceAll(java.util.function.BiFunction);
public abstract int size();
public abstract void putAll(java.util.Map);
public java.lang.Object putIfAbsent(java.lang.Object, java.lang.Object);
public abstract java.util.Set keySet();
public abstract boolean containsValue(java.lang.Object);
public abstract boolean containsKey(java.lang.Object);
public java.lang.Object getOrDefault(java.lang.Object, java.lang.Object);
public void forEach(java.util.function.BiConsumer);
...
}
複製程式碼
可以看出來就是 大小,加對映,刪對映,用鍵查值,是否空 等等,這些對映最基礎的功能。還有些檢視的部分,下篇文章具體講
Collection的子介面
List
有序集合,新加支援隨機訪問功能:
- add(n, 元素)
- remove(n)
- get(n)
- set(n, 元素)
Set
- 元素不重複,所以要適當的定義
equals
方法; - 子介面
SortedSet
,故名思義是排好序的,所以要適當的定義比較器 SortedSet
的子介面NavigableSet
中設計了一些搜素,遍歷的方法
Queue
- 入隊尾,出對頭
- 子介面
Qeque
雙端佇列,兩頭都可以出入
Map的子介面
其實和Set
差不多
- 子介面
SortedMap
,故名思義是排好序的,所以要適當的定義比較器 SortedMap
的子介面NavigableMap
中設計了一些搜素,遍歷的方法
對介面的實現
List
LinkedList(連結串列)
java中的連結串列都是雙向的(有前驅後驅)。重點講下它的迭代器ListIterator
- 初始位置: |ABCD
iter.next
: A|BCDiter.previous
: |ABCDiter.add
: 把元素加到游標|
之前,注意是之前iter.remove
必須在it.next
或it.previous
使用之後使用,把游標經過的元素刪除
連結串列使用注意:
- 使用連結串列是可以減少在列表中間插入刪除元素所付出的代價。
- 避免使用以整數索引連結串列中的位置,這樣效率很低
ArrayList(陣列列表)
ArrayList
: 動態泛型陣列列表,可以自動調節陣列容量。當需要隨機訪問時使用它效率更高,不用連結串列。
講下capacity
和size
的區別:
new ArrayList<>(100)
100 是capacity
,是初始容量,如果實際size超過它,容量會自動增加array.size()
返回的是陣列列表內元素實際的個數。
p.s. 這和c++的 vector
很像
Set
HashSet(雜湊集)
HashSet
: 基於雜湊表的Set,內部用連結串列陣列實現。初始化時可以指定容量和裝填因子。- 由於HashSet訪問是隨機的,所以當不需要關心集合中的順序時才使用它。
- 子類
LinkedHashSet
,裡面的元素之間是雙向連結串列,迭代器是按插入順序進行訪問的。
TreeSet(樹集)
-TreeSet
: 實現SortedSet
介面,內部基於紅黑樹。由於是有順序的,所以使用者一般要自定義比較器。迭代器是按排序順序進行訪問的。
- 當不需要順序時,用
HashSet
,因為它更快。 - 可以實現升級版
NavigableSet
介面,higher(v),lower(v),pollFirst(),pollLast(),反向迭代 等等。
Queue
一般用它的升級版Deque
,而Deque
可以由ArrayDeque
和LinkedList
實現。下面主要介紹PriorityQueue
PriorityQueue(優先順序佇列)
PriorityQueue
:優先順序佇列,內部基於堆(heap)。- 按任意順序插入,卻總是按排序順序輸出最小值。
PriorityQueue<Type> pq = new PriorityQueue();
,從左邊可以看出這貨是類。
Map
HashMap
- 顧名思義和
HashSet
差不多,只不過是對建進行雜湊。 - 子類
LinkedHashMap
,注意連結串列散射對映,迭代器是按訪問順序進行訪問的。每次呼叫 get 或 put, 受到影響的條目將從當前的位置刪除,並放到條目連結串列的尾部。
TreeMap
- 顧名思義和
HashMap
差不多,只不過是對建進行紅黑樹排序。 - 同樣 當不需要順序時,用
HashMap
,因為它更快.
一些技巧:
- 遍歷Map:
scores.forEach((k, v) -> // 訪問 k, v 的最快方法
System.out.println("key=" + k + ", value" + v));
複製程式碼
- 用 Map 計數:
scores.put("Jack", scores.getOrDefault("Jack", 0) + 1); // 方法1
scores.merge("Jack", 1, Integer::sum); // 方法2
複製程式碼
WeekHashMap
弱雜湊對映:當對鍵的唯一引用來自雜湊條目時,這一資料結構將與垃圾回收器協同工作一起刪除鍵 / 值對。也就是當某個值沒用了它會被自動回收。
IdentityHashMap
IdentityHashMap
中 鍵的雜湊值 不是用 hashCode 函式計算的,而是用System.identityHashCode
方法計算的(Object.hashCode
方法根據物件的記憶體地址來計算雜湊碼時所使用的方式)。- 所以,在對兩個物件進行比較時,IdentityHashMap 使用 == , 而不使用equal。也就是不同的鍵物件,即使內容相同,也被視為是不同的物件。
- 在實現物件遍歷演算法 (如物件序列化)時,可以它用來跟蹤每個物件的遍歷狀況。
遺留的集合
看看就好,遇到時再查書
本文示例程式碼:github