【Java】容器相關知識點
轉貼地址:https://blog.csdn.net/albertfly/article/details/52403393
Java實用類庫提供了一套相當完整的容器來幫助我們解決很多具體問題。因為我本身是一名Android開發者,包括我在內很多安卓開發,最拿手的就是ListView(RecycleView)+BaseAdapter+ArrayList三劍客, 平時接觸使用的容器也只有ArrayList和HashMap。導致對於整個Java容器體系的掌握和使用還停留在很淺的層面。省不足而思改進,那麼跟著我來總結一下Java容器的相關知識吧。
目錄
目錄
CopyOnWriteArrayList與Copy-On-Write策略
java容器類的繼承結構
Java容器類庫定義了兩個不同概念的容器,Collection和Map
- Collection 一個獨立元素的序列,這些元素都服從一條或多條規則。List必須按照插入的順序儲存元素。Set不能有重複元素。Queue按照排隊規則來確定物件產生的順序。
(文中Jdk原始碼版本無特殊說明均為jdk1.8.0_101)
public interface Collection<E> extends Iterable<E> {
int size();
boolean isEmpty();
boolean contains(Object o);
Iterator<E> iterator();
Object[] toArray();
<T> T[] toArray(T[] a);
boolean add(E e);
boolean remove(Object o);
boolean containsAll(java.util.Collection<?> c);
boolean addAll(java.util.Collection<? extends E> c);
boolean removeAll(java.util.Collection<?> c);
... //省略了其他方法
}
}
可以看到,java定義了Collection介面和內部集合的基本操作方法,Collection預設可以進行對集合末端新增元素,刪除指定元素等操作。List、Set、Queue介面都繼承自Collection並定義了各自不同的方法。
- Map 一組成對的”鍵值對”物件,允許我們使用鍵來查詢值。
public interface Map<K,V> {
int size();
boolean containsKey(Object key);
boolean containsValue(Object value);
V get(Object key);
V put(K key, V value);
V remove(Object key);
void putAll(java.util.Map<? extends K, ? extends V> m);
void clear();
Set<K> keySet();
Collection<V> values();
Set<java.util.Map.Entry<K, V>> entrySet();
interface Entry<K,V> {
K getKey();
V getValue();
V setValue(V value);
boolean equals(Object o);
int hashCode();
...
}
boolean equals(Object o);
int hashCode();
}
Map內部介面Entry<K,V>對應著Map的鍵值對。
具體介紹
迭代器
先介紹一下迭代器。迭代器本身也是一種設計模式,設計的初衷在於:容器的實現由很多種,而我們想對容器進行遍歷操作的話,首先不應該關心容器實現的細節,其次遍歷操作應該是輕量級的。迭代器統一了對容器的訪問方式,同時建立它的代價很小。值得注意的是,Iterator只能單向移動。
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
通過容器的iterator()方法拿到容器的迭代器
迭代器的next()獲取下一個元素
hasNext()判斷是否還有元素
remove()刪除指定元素
ListIterator
ListIterator是Iterator的擴充套件之內,用於各種List類訪問,支援雙向移動。
Collection
List
List 承諾可以將元素維護在特定的序列中.List介面在Collection的基礎上新增了大量的方法,使得可以再List中間插入和移除元素。
public interface List<E> extends Collection<E> {
...
boolean add(E e);
boolean remove(Object o);
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
boolean addAll(int index, Collection<? extends E> c);
boolean removeAll(Collection<?> c);
boolean retainAll(Collection<?> c);
E get(int index);
E set(int index, E element);
void add(int index, E element);
E remove(int index);
int indexOf(Object o);
int lastIndexOf(Object o);
java.util.List<E> subList(int fromIndex, int toIndex);
...
}
有兩種型別的List,ArrayList和LinkedList
List型別 | 優點 | 缺點 | 底層實現 |
---|---|---|---|
ArrayList | 隨機訪問元素較快 | 中間元素的插入和刪除較慢 | 陣列 |
LinkedList | 中間元素的插入和刪除,順序訪問的優化 | 隨機訪問元素較慢 | 雙向連結串列 |
Set
Set不儲存重複的元素,通常用於快速查詢元素。值得一提的是,Set具有與Collection完全一樣的介面,沒有任何額外的功能。 存入的元素必須定義equals()方法
Set型別 | 使用場景 | 底層實現 |
---|---|---|
HashSet | 快速查詢,元素必須定義hashCode() | 連結串列 |
TreeSet | 保持次序,元素必須實現Comparable介面 | 紅-黑樹結構 |
LinkedHashSet | 維護次序的HashSet, 元素必須定義hashCode() | 連結串列 |
Queue
除了併發應用,Queue僅有的兩個實現是LinkedList和PriorityQueue, 其中LinkedList同時實現了List, Deque介面。它們的差異在於排序行為而不是效能。
public interface Queue<E> extends Collection<E> {
boolean add(E e);
boolean offer(E e);
E remove();
E poll();
E element();
E peek();
}
Map
Map型別 | 使用場景 | 底層實現 |
---|---|---|
HashMap | 快速查詢 | 雜湊表 |
LinkedHashMap | 迭代遍歷具有順序(插入順序 or 最近最少使用) | 連結串列 |
TreeMap | 具有排序,唯一可以返回子樹的Map(subMap()) | 紅-黑樹結構 |
WeakHashMap | 弱鍵對映,對映之外無引用的鍵,可以被垃圾回收 | 雜湊表 |
ConcurrentHashMap | 執行緒安全的Map | 連結串列 |
IdentityHashMap | 使用==代替equals()對鍵進行排序,專位解決特殊問題 | 連結串列 |
我們可以手工調整HashMap來調整效能,涉及到如容量、初始容量、尺寸、負載因子等概念。感興趣的話可以看一些相關資料。
一些建議
不要使用過時的容器 如Vector Enumeration Hashtable Stack(沒錯,這就是java最初的糟糕設計,實際中使用棧的話推薦LinkedList)
進階·併發容器
這裡不會討論的太細緻的實現,僅僅簡單介紹一下基礎知識,感興趣的可以閱讀《Java 併發程式設計的藝術》這本書。
CopyOnWriteArrayList與Copy-On-Write策略
Copy-On-Write簡稱COW,是一種用於程式設計中的優化策略。其基本思路是,從一開始大家都在共享同一個內容,當某個人想要修改這個內容的時候,才會真正把內容Copy出去形成一個新的內容然後再改,這是一種延時懶惰策略。從JDK1.5開始Java併發包裡提供了兩個使用CopyOnWrite機制實現的併發容器,它們是CopyOnWriteArrayList和CopyOnWriteArraySet。CopyOnWrite容器非常有用,可以在非常多的併發場景中使用到。
CopyOnWrite容器即寫時複製的容器。通俗的理解是當我們往一個容器新增元素的時候,不直接往當前容器新增,而是先將當前容器進行Copy,複製出一個新的容器,然後新的容器裡新增元素,新增完元素之後,再將原容器的引用指向新的容器。這樣做的好處是我們可以對CopyOnWrite容器進行併發的讀,而不需要加鎖,因為當前容器不會新增任何元素。所以CopyOnWrite容器也是一種讀寫分離的思想,讀和寫不同的容器。
CopyOnWrite容器只能保證資料的最終一致性,不能保證資料的實時一致性。所以如果你希望寫入的的資料,馬上能讀到,請不要使用CopyOnWrite容器。
ConcurrentLinkedQueue
在併發程式設計中,有時候需要使用執行緒安全的佇列或列表。通常實現執行緒安全有兩種方式,一種是使用阻塞演算法,一種是使用非阻塞演算法。非阻塞演算法實現基礎為迴圈CAS(Compare and Swipe 比較和交換)。
ConcurrentLinkedQueue技術上的實現與CopyOnWriteArrayList與Copy類似,但是容器只有部分內容而不是整個容器可以被複制和修改。ConcurrentLinkedQueue有head節點和tail節點組成,每個節點由節點元素(item)和指向下一個結點(next)的引用組成。節點之間通過next關聯起來,形成一張連結串列結構的佇列。
ConcurrentHashMap與鎖分段技術
ConcurrentHashMap是執行緒安全且高效的HashMap。多執行緒環境下,使用非執行緒安全的HashMap會導致死迴圈,而如文章中建議的那樣,HashTable這種過時容器效率低下(使用synchronized來保證執行緒安全)。ConcurrentHashMap使用鎖分段技術,大大提高了併發使用的效率。
鎖分段技術: 假設容器有多把鎖,每一把鎖用於鎖容器其中一部分資料,當多執行緒訪問容器不同資料段資料時,執行緒間就不存在鎖競爭,從而提高併發訪問效率。
阻塞佇列
JDK7 提供了7個阻塞佇列,實現原理都是基於生產-消費模式的等待通知機制。
阻塞佇列型別 | 特點 |
---|---|
ArrayBlockingQueue | 由陣列結構組成的有界阻塞佇列 |
LinkedBlockingQueue | 由連結串列結構組成的有界阻塞佇列 |
PriorityBlockingQueue | 支援優先順序排序的無界阻塞佇列 |
DelayQueue | 使用優先順序佇列實現的無界阻塞佇列 |
SynchronousQueue | 不儲存元素的阻塞佇列 |
LinkedTransferQueue | 由連結串列結構組成的無界阻塞佇列 |
LinkedBlockingQueue | 由連結串列結構組成的雙向阻塞佇列 |
相關文章
- Java容器相關知識點整理Java
- redis相關知識點Redis
- Git相關知識點Git
- Java併發相關知識點梳理和研究Java
- LR模型相關知識點模型
- ivar layout 相關知識點
- Java知識點總結(Java容器-List)Java
- Java知識點總結(Java容器-Vector)Java
- Java知識點總結(Java容器-Set)Java
- React相關知識點:關於ReduxReactRedux
- 總結 MySQL 相關知識點MySql
- JVM相關知識點總結JVM
- 資料庫相關知識點提要資料庫
- Spring和Springboot相關知識點整理Spring Boot
- Java多執行緒相關知識Java執行緒
- 異常處理及其相關知識點
- GreatSQL統計資訊相關知識點SQL
- 面試系列之View相關知識點面試View
- Fragment 相關知識點都在這裡了Fragment
- Java虛擬機器垃圾回收相關知識點全梳理(上)Java虛擬機
- .net相關知識
- Shell相關知識
- RPM相關知識
- Java與Mysql鎖相關知識總結JavaMySql
- 記錄Java執行緒相關知識Java執行緒
- 資料庫相關知識點(秋招整理)資料庫
- 關於Hibernate和hql語句的相關知識點
- upload-labs通關詳解以及相關知識點
- /proc的相關知識
- 音訊相關知識音訊
- Redis的相關知識Redis
- SSL相關知識科普
- Elasticsearch——search相關知識Elasticsearch
- 連結串列、棧、佇列、KMP相關知識點佇列KMP
- JavaScript相關知識點優秀部落格收錄JavaScript
- 相機成像相關知識總結
- 關於Java兩點需要更新的知識Java
- Java容器(List、Set、Map)知識點快速複習手冊Java