Java容器型別使用總結
最近抽空把java.lang下面常用的那些容器型別(資料結構)複習了一下,這些東西是基礎,平時使用的時候也可以很容易查得到,有些方法大概知道,但是總是弄混,如果可以記住那些重要方法,並且能夠熟練使用的話,還是可以讓編碼過程變得容易很多。另外一個是實現機制,對於常用資料結構的實現機制,應該說是必須要熟知的。
另外,併發容器我之前整理過,放在這篇文章裡。
Queue
- add和offer的區別在於達到上限時add丟擲異常,offer返回false;
- remove和poll的區別在於,佇列為空時前者丟擲異常,後者返回空;
- element和peek都返回佇列頭部元素,但是前者失敗不丟擲異常,後者返回空。
boolean add(E e); boolean offer(E e); E remove(); E poll(); E element(); E peek();
PriorityQueue,內部實現是一個Object[] queue承載的堆。
Deque,雙端佇列(double-ended queue),在Queue基礎上,增加了這樣幾個方法:
void addFirst(E e); void addLast(E e); boolean offerFirst(E e); boolean offerLast(E e); E removeFirst(); E removeLast(); E pollFirst(); E pollLast(); E getFirst(); E getLast(); E peekFirst(); E peekLast(); boolean removeFirstOccurrence(Object o); boolean removeLastOccurrence(Object o);
ArrayDequeue:陣列實現,擴容策略是容量翻倍。
List
boolean add(E e); boolean remove(Object o); E get(int index); E set(int index, E element); void add(int index, E element); E remove(int index);
ArrayList,擴容策略是(oldCapacity * 3)/2 + 1。
LinkedList,它除了實現自List介面外,還實現了Deque介面。
Vector,實現自List介面,內部實現是個陣列,執行緒安全,擴容策略是(capacityIncrement > 0) ? (oldCapacity + capacityIncrement) : (oldCapacity * 2)。
Stack是Vector的子類,增加了一些棧的方法:
E push(E item) E pop() E peek() boolean empty()
Map
boolean containsKey(Object key); boolean containsValue(Object value); V get(Object key); V put(K key, V value); V remove(Object key); Set<K> keySet(); Collection<V> values(); Set<Map.Entry<K, V>> entrySet();
SotedMap介面,key是有序的map:
SortedMap<K, V> subMap(K paramK1, K paramK2); SortedMap<K, V> headMap(K paramK); SortedMap<K, V> tailMap(K paramK); K firstKey(); K lastKey();
子介面NavigableMap,提供了一些根據某個key尋找它前面或者後面的key的方法。其中floorKey/celingKey表示的關係是小於等於/大於等於,lower/higher表示的關係是嚴格的小於/大於:
Map.Entry<K,V> floorEntry(K key) K floorKey(K key) Map.Entry<K,V> ceilingEntry(K key) K ceilingKey(K key) Map.Entry<K,V> lowerEntry(K key) K lowerKey(K key) Map.Entry<K,V> higherEntry(K key) K higherKey(K key)
TreeMap是NavigableMap的直接實現子類,內部實現是一個紅黑樹。
EnumMap,結構是<K extends Enum<K>, V>,內部是通過一個K[] keyUniverse和一個Object[] vals來實現的。
HashMap,內部是陣列+連結串列實現的,達到threshold = capacity * loadFactor時,擴容策略為:numKeysToBeAdded / loadFactor + 1。
HashTable,實現自Dictionary和Map,方法都是執行緒安全的。HashTable的put方法,value不可以為空,這是它和HashMap的一個不同;再有二者找桶的hash方法不同;最後則是threshold計算邏輯相同,但它的擴容策略不同:oldCapacity * 2 + 1。HashTable、HashMap和HashSet經常被放到一起比較。
Properties,是HashTable的子類,方法執行緒安全。
IdentityHashMap,比較key不是使用equals來比較,而是使用“==”來比較,只要地址不等(即不是同一個物件)即可共存,也就是說,key是可以重複的。
LinkedHashMap,在HashMap的基礎上,又單獨維護了一個雙向迴圈連結串列。有一個重要引數是accessOrder,accessOrder為true時,每次呼叫get方法訪問行為發生後,會把最近訪問的物件移動到頭部,而超出容量移除物件時,是從尾部開始的,利用它並且覆寫boolean removeEldestEntry方法可以實現一個LRU的佇列。
WeakHashMap,但是key是weak引用,在不被使用時自動清除,擴容策略:tab.length * 2。原理上看:Entry<K,V> extends WeakReference<K> implements Map.Entry<K,V>,因此entry是弱引用的實現類,關鍵方法是expungeStaleEntries,它在對這個map各種操作的時候都會被呼叫到,而這個方法裡面也是靠監聽key的ReferenceQueue這個佇列的狀態來確定是否真的沒有物件引用了。
Set
boolean contains(Object o); boolean add(E e); boolean remove(Object o);
SortedSet,介面方法和SortedMap類似:
SortedSet<E> subSet(E fromElement, E toElement); SortedSet<E> headSet(E toElement); SortedSet<E> tailSet(E fromElement); E first(); E last();
相應地,NavigableSet和NavigableMap類似,方法就不列出了。
TreeSet則和TreeMap類似,其實內部實現就是一個TreeMap。
HashSet,尤其注意的是,有兩種實現,當構造方法引數小於3個時,內部使用HashMap,否則,使用LinkedHashMap。
RegularEnumSet和JumboEnumSet,前者是普通的列舉set(用位移來表示各種組合的可能,達到空間佔用最小,最大不能超過64個列舉值),後者適合數量較大的列舉set(老老實實地使用物件陣列)。
LinkedHashSet,其實和LinkedHashMap是一個東西。
BitSet,叫set但是沒有實現set的介面。用位元位來存放某個數是否存在,比如僅僅一個long,64位,就可以存放0~63的數,內部實際的資料型別是long[]。
void flip(int bitIndex); void flip(int fromIndex, int toIndex); void set(int bitIndex); void set(int fromIndex, int toIndex, boolean value); void clear(int bitIndex); int length(); int size();
其中size方法返回實際使用了的位元位數目;length方法返回邏輯意義上的長度(比如表示的數裡面最大是80,那麼加上0,它的邏輯意義上的長度就是81)。
擴容策略:Math.max(2 * words.length, wordsRequired)。
Dictionary
Enumeration<K> keys(); Enumeration<V> elements(); V get(Object key); V put(K key, V value); V remove(Object key);
已經被廢棄了,用Map來實現相同功能。
最後這張圖來自這個網站,對於從巨集觀上把握這些容器型別實在是太有幫助了:
相關文章
- Java 容器系列總結Java
- Redis中 HyperLogLog資料型別使用總結Redis資料型別
- Java知識點總結(Java容器-List)Java
- Java知識點總結(Java容器-Vector)Java
- Java知識點總結(Java容器-Set)Java
- JavaScript基本型別總結JavaScript型別
- OOM異常型別總結OOM型別
- [python] Python型別提示總結Python型別
- JS 資料型別總結JS資料型別
- Java知識點總結(Java泛型)Java泛型
- Python的資料型別總結Python資料型別
- 後臺面試型別總結面試型別
- Go 的資料型別總結Go資料型別
- 【bpmn.js 使用總結】指定 Palette 容器JS
- Redis set資料型別命令使用及應用場景使用總結Redis資料型別
- JavaScript變數型別檢測總結JavaScript變數型別
- Mysql支援的資料型別(總結)MySql資料型別
- Python str型別學習總結(一)Python型別
- Flume 總結(三)sources型別-1.9.0新版型別
- go 基礎總結 --- 資料型別Go資料型別
- JavaScript資料型別轉換總結JavaScript資料型別
- PHP弱型別安全問題總結PHP型別
- Java基本資料型別總結、型別轉換、常量的宣告規範,final關鍵字的用法Java資料型別
- 【Java】sleep和wait區別總結JavaAI
- 容器,型別轉換。List。型別
- JS基礎總結(1)——資料型別JS資料型別
- JAVA 解析html 型別字串(使用jsoup)JavaHTML型別字串JS
- Redis 中ZSET資料型別命令使用及對應場景總結Redis資料型別
- 可變資料型別(mutable)與不可變資料型別(immutable)總結資料型別
- 演算法型別大總結(並附經典題型)演算法型別
- golang 中的四種型別轉換總結Golang型別
- 泛型總結泛型
- Python3學習(基本資料型別-集合-字典-基本資料型別總結)Python資料型別
- 【乾貨】驗證碼的常見型別總結型別
- C++的資料型別總結,不能錯過C++資料型別
- c# 操作Redis的五種基本型別總結C#Redis型別
- Enum列舉型別實戰總結,保證有用!型別
- SpringMVC-方法四種型別返回值總結SpringMVC型別
- Java常見知識點彙總(①)——資料型別Java資料型別