轉載請保留原文鏈接: http://dashidan.com/article/java/basic/15.html
15.Java集合類
Java集合類是java提供的工具包,包含了常用的數據結構:集合、鏈表、隊列、棧、映射等.Java集合類主要可以劃分爲4個部分:List列表、Set集合、Map映射、工具類(Iterator迭代器、Enumeration枚舉類、Arrays和Collections).
① 常用集合類接口
常用集合類繼承關係如下所示:
Collection |-List |-LinkedList |-ArrayList |-Vector |-Set |-HashSet |-Queue Map |-Hashtable |-HashMap
1.Collection
接口
Collection
是最基本的集合接口,一個Collection
代表一組Object,即Collection
的元素(Elements).由Collection
接口派生的兩個接口是List
和Set
.List
允許有相同元素, Set
不允許有相同元素.
實現Collection接口的類都必須提供兩個標準的構造函數:
無參數的構造函數用於創建一個空的Collection.
有一個參數的構造函數用於創建一個新的
Collection
對象,這個對象傳入的Collection
有相同的元素. 允許用戶複製一個Collection
.
2.List
接口
List
是有序
的Collection
. 使用此接口能夠精確的控制每個元素插入的位置.能夠使用索引(元素在List中的位置,類似於數組下標)來訪問List中的元素,這類似於Java的數組.
除了具有Collection
接口必備的iterator()
方法外, List
還提供一個listIterator()
方法, 返回一個ListIterator
接口,和標準的Iterator
接口相比,ListIterator
多了一些add()
之類的方法,允許添加,刪除,設定元素,還能向前或向後遍歷.
實現List接口的常用類有LinkedList
,ArrayList
,Vector
和Stack
. 和Set
不同, List
允許有相同的元素.
3.Set
接口
Set
是一種不包含重複的元素的Collection
,即任意的兩個元素e1
和e2
都有e1.equals(e2)=false
.
Set
的構造函數有一個約束條件,傳入的Collection
參數不能包含重複的元素.Set
最多有一個null
元素.
必須小心操作可變對象(Mutable Object)
如果一個`Set`中的可變元素改變了自身狀態導致Object.equals(Object)=true將導致一些問題.
4.Queue
接口
可以實現先進先出的隊列.LinkedList
同樣實現了Queue接口.PriorityQueue
用來創建自然排序的優先級隊列.
5.Map
接口
Map
提供key
到value
的映射. 一個Map
中不能包含相同的key
,每個key
只能映射一個value
.Map
的內容可以被當作一組key
集合,一組value
集合,或者一組key-value
映射.
`Map`沒有繼承`Collection`接口.
② 常用集合類
1.LinkedList
類
LinkedList
實現了List
接口,允許null元素.提供額外的get
,remove
,insert
方法在LinkedList
的首部或尾部.這些操作使LinkedList
可被用作棧
(stack),隊列
(queue)或雙向隊列
(deque).
`LinkedList`沒有同步方法
如果多個線程同時訪問一個List, 則必須自己實現訪問同步.
一種解決方法是在創建List時構造一個同步的List:
List list = Collections.synchronizedList(new LinkedList(...));.
2.ArrayList
類
ArrayList
實現了變長數組.它允許所有元素,包括null.每個ArrayList
實例都有一個容量(Capacity
), 即用於存儲元素的數組的大小.這個容量可隨着不斷添加新元素而自動增加,但是增長算法並沒有定義.
當需要插入大量元素時,在插入前可以調用ensureCapacity
方法來增加ArrayList
的容量以提高插入效率.
和LinkedList一樣,ArrayList也是非同步的(unsynchronized).
ArrayList
添加刪除對象:
/** ArrayList添加對象*/ArrayList<Integer> intList = new ArrayList<>();System.out.println("ArrayList 長度: " + intList.size());for (int i = 0; i < 10; i++) { intList.add(i);}System.out.println("ArrayList 長度: " + intList.size());/** ArrayList刪除對象*/intList.remove(5);System.out.println("ArrayList 長度: " + intList.size());
ArrayList
遍歷:
ArrayList 遍歷方式 1 增強for循環, 獲得值, 無法獲得索引
for (Integer intNum : arrayList) { System.out.println(intNum);}
ArrayList 遍歷方式 2普通for循環, 索引和值都能獲得
for (int i = 0; i < arrayList.size(); i++) { int num = arrayList.get(i); System.out.println(num);}
ArrayList 遍歷方式 3 迭代器 Itertor, 無法獲得索引
Iterator<Integer> it = arrayList.iterator();while (it.hasNext()) { int num = it.next(); System.out.println(num);}
3.Vector
類
Vector
非常類似ArrayList
,但Vector
是線程同步的.
由Vector
創建的Iterator
,雖然和ArrayList
創建的Iterator
是同一接口,但由於Vector
是線程同步的,當一個Iterator
被創建而且正在被使用,另一個線程改變了Vector
的狀態(例如,添加或刪除了一些元素),這時調用Iterator
的方法時將拋出ConcurrentModificationException
,因此必須捕獲該異常.
代碼示例:
/** Vector*/Vector<Integer> vector = new Vector<>();System.out.println("Vector 長度: " + vector.size());for (int i = 0; i < 5; i++) { vector.add(i);}System.out.println("Vector 長度: " + vector.size());/** Vectort 刪除對象*/vector.remove(3);System.out.println("Vector 長度: " + vector.size());/** Vectort 遍歷方式 1 增強for循環*/for (Integer intNum : vector) { System.out.println(intNum);}
Vector添加刪除對象和遍歷方式和ArrayList類似, 參考ArrayList的代碼實現.
4.Stack
類
Stack
繼承自Vector
,實現一個後進先出
的堆棧. stack
的常用方法:
push
: 放入棧pop
: 出棧peek
:得到棧頂的元素empty
:測試堆棧是否爲空search
:檢測一個元素在堆棧中的位置
代碼示例:
/** Stack*/Stack<Integer> stack = new Stack<>();System.out.println("Stack 長度: " + stack.size());for (int i = 0; i < 5; i++) { /** 入棧*/ stack.push(i);}System.out.println("Stack 長度: " + stack.size());/** Stack pop 出棧*/stack.pop();System.out.println("Stack 長度: " + stack.size());/** Stack peek 得到棧頂的元素*/int peekNum = stack.peek();System.out.println("Stack peekNum: " + peekNum);/** Stack search 檢測一個元素在堆棧中的位置*/int pos = stack.search(3);System.out.println("Stack search pos: " + pos);/** Stack 遍歷方式 1 增強for循環*/for (Integer anIntList : stack) { int num = anIntList; System.out.println(num);}
`Stack`遍歷方式和`ArrayList`類似, 參考`ArrayList`的代碼實現.
5.HashMap類
HashMap
是最常用的Map
,不是線程安全的.它根據鍵的HashCode
值存儲數據,根據鍵可以直接獲取它的值,具有很快的訪問速度.遍歷時,取得數據的順序是完全隨機
的.
由於鍵對象不可以重複, 所以HashMap
最多隻允許一條記錄的鍵爲空(null),允許多條記錄的值爲空(null).
由於作爲key的對象將通過計算其散列函數
來確定與之對應的value
的位置, 因此任何作爲key
的對象都必須實現hashCode
和equals
方法.
`hashCode`和`equals`方法繼承自根類`Object`.
用自定義的類當作key
按照`散列函數`的定義,如果兩個對象相同,即`obj1.equals(obj2)=true`,則它們的`hashCode`必須相同,但如果兩個對象不同,則它們的`hashCode``不一定不同`.
如果兩個不同對象的hashCode相同,這種現象稱爲`衝突`. 衝突會導致操作哈希表的時間開銷增大.
所以儘量定義好的`hashCode()`方法,能加快哈希表的操作.如果相同的對象有不同的`hashCode`,對哈希表的操作會出現意想不到的結果(`期待的get方法返回null`).
要避免這種問題,只需要牢記一條:要同時覆寫`equals`方法和`hashCode`方法, 而不要只寫其中一個.
代碼示例: HashMap
添加和刪除對象:
HashMap<Integer, Integer> hashMap = new HashMap<>();System.out.println("HashMap 長度: " + hashMap.size());for (int i = 0; i < 5; i++) { /** HashMap 添加對象*/ hashMap.put(i, 100 + i);}System.out.println("HashMap 長度: " + hashMap.size());/** HashMap 刪除對象*/hashMap.remove(2);System.out.println("HashMap 長度: " + hashMap.size());
HashMap
遍歷:
HashMap 遍歷方式 1 增強for循環遍歷 Entry
推薦使用
直接拿到了key和value的對象, 省去了`get`數據的操作,效率最高.
System.out.println("HashMap 遍歷方式 1 增強for循環遍歷 Entry ");for (Map.Entry<Integer, Integer> entry : hashMap.entrySet()) { System.out.println("hashMap key: " + entry.getKey() + " hashMap value: " + entry.getValue());}
HashMap 遍歷方式 2 通過迭代器遍歷 key
Iterator<Integer> it0 = hashMap.keySet().iterator();while (it0.hasNext()) { int key = it0.next(); int value = hashMap.get(key); System.out.println("key: " + key + " value: " + value);}
HashMap 遍歷方式 3 通過 增強for循環遍歷 key
for (Integer key : hashMap.keySet()) { int value = hashMap.get(key); System.out.println("key: " + key + " value: " + value);}
HashMap 遍歷方式 4 通過迭代器遍歷 values, 無法得到 key值
Iterator<Integer> it1 = hashMap.values().iterator();while (it1.hasNext()) { int value = it1.next(); System.out.println("value: " + value);}
HashMap 遍歷方式 5 通過 增強for循環遍歷 values, 無法得到 key值
for (Integer value : hashMap.values()) { System.out.println("value: " + value);}
6.Hashtable
類
Hashtable
繼承Map
接口,實現一個key-value
映射的哈希表. 任何非空
(non-null)的對象都可作爲key
或者value
.Hashtable
與HashMap
類似,是HashMap
的線程安全版,是線程同步的,即任一時刻只有一個線程能寫Hashtable
,因此也導致了Hashtale在寫入時會比較慢. 它繼承自Dictionary
類,不同的是它不允許記錄的鍵或者值爲null
,同時效率較低.
建議使用ConcurrentHashMap替代
如果需要線程同步的map, 建議使用線程同步的ConcurrentHashMap類. 不建議使用這個類, 並沒有示例代碼.
7.WeakHashMap
類
WeakHashMap
是一種改進的HashMap
. 它對key
實行弱引用
,如果一個key
不再被外部所引用,那麼該key
可以被Java的垃圾回收器
(GC)回收.
使用方式同`HashMap`.
8. HashSet
類
HashSet
中元素是無序的(這個無序指的是數據的添加順序和後來的排列順序不同),而且元素不可重複.
HashSet
的底層是數組,在增加和刪除的時候由於運用的hashCode
的比較來確定添加元素的位置,不存在元素的偏移, 因此查詢和刪除和增加元素的效率都非常高.
但是HashSet
增刪的高效率是通過花費大量的空間換來的, 因爲空間越大,取餘數相同的情況就越小.HashSet
這種算法會建立許多無用的空間.
使用HashSet類時如果發生衝突,就會出現遍歷整個數組的情況,這樣就使得效率非常的低.
/** 循環兩次,放入重複的1-5*/for (int i = 0; i < 5; i++) { hashSet.add(i);}for (int i = 0; i < 5; i++) { hashSet.add(i);}System.out.println("HashSet 長度: " + hashSet.size());/** HashSet 遍歷方式 1 增強for循環*/for (Integer intNum : hashSet) { System.out.println(intNum);}
由於HashSet去重功能, 第二次循環插入重複數據時, HashSet中並沒有加入新的數據, 長度依然是5. HashSet的遍歷方式同ArrayList,參考ArrayList的遍歷.
9.ConcurrentHashMap
類
線程同步的HashMap
,線程安全並且鎖分離. ConcurrentHashMap
內部使用段(Segment
)來表示這些不同的部分,每個段其實就是一個小的hash table
,它們有自己的鎖. 只要多個修改操作發生在不同的段上,它們就可以併發進行.
使用方式同`HashMap`.
10.LinkedHashMap
類
有序的HashMap
, 非線程安全. LinkedHashMap
保存了記錄的插入順序,在用Iteraor
遍歷LinkedHashMap
時,先得到的記錄肯定是先插入的,在遍歷的時候會比HashMap
慢,有HashMap的全部特性.
使用方式同`HashMap`.
11.TreeMap
類
TreeMap
實現SortMap
接口,能夠把它保存的記錄根據鍵排序,默認是按鍵值的升序排序(自然順序),也可以指定排序的比較器. 當用Iterator
遍歷TreeMap
時, 得到的記錄是排過序的.
TreeMap
不允許key
值爲空
,非線程同步.
使用方式同`HashMap`.
11.總結
如果涉及到堆棧,隊列等操作,應該考慮用
List
. 對於需要快速插入,刪除元素,應該使用LinkedList
, 如果需要快速隨機訪問元素,應該使用ArrayList
.如果程序在單線程環境中,或者訪問僅僅在一個線程中進行,考慮
非同步
的類,其效率較高.如果多個線程可能同時操作一個類,應該使用同步的類.
要特別注意對哈希表的操作,作爲
key
的對象要正確覆寫equals
和hashCode
方法.儘量返回接口而非實際的類型, 如返回
List
而非ArrayList
, 這樣如果以後需要將ArrayList
換成LinkedList
時, 代碼接口不用改變.擴展性強.
③ 常用遍歷集合方式
1. 迭代器Iterator
不論Collection
的實際類型如何,它都支持一個iterator()
的方法,該方法返回一個迭代器,使用該迭代器即可逐一訪問Collection
中每一個元素.典型的用法如下:
// 獲得一個迭代器Iterator it = collection.iterator();while(it.hasNext()) { //獲取下一個元素 Object obj = it.next();}
2. foreach
增強for循環, JDK1.5之後提供的新功能, 可以輸出數組或集合.
3. for循環
普通for循環遍歷
示例代碼:
package com.dashidan.lesson13;import java.util.*;/** * 大屎蛋教程網-dashidan.com * <p> * Java教程基礎篇: 13.Java集合類 */public class Demo1 { public static void main(String[] args) { testArrayList(); testVector(); testStack(); testHashMap(); testHashSet(); } /** * ArrayList基本操作 */ public static void testArrayList() { System.out.println("---ArrayList---"); /** ArrayList添加對象*/ ArrayList<Integer> arrayList = new ArrayList<>(); System.out.println("ArrayList 長度: " + arrayList.size()); for (int i = 0; i < 5; i++) { arrayList.add(i); } System.out.println("ArrayList 長度: " + arrayList.size()); /** ArrayList刪除對象*/ arrayList.remove(3); System.out.println("ArrayList 長度: " + arrayList.size()); /** ArrayList 遍歷方式 1 增強for循環, 獲得值, 無法獲得索引*/ for (Integer intNum : arrayList) { System.out.println(intNum); } /** ArrayList 遍歷方式 2普通for循環, 值和索引都能得到*/ for (int i = 0; i < arrayList.size(); i++) { int num = arrayList.get(i); System.out.println(num); } /** ArrayList 遍歷方式 3 迭代器 Itertor, 獲得值, 無法獲得索引*/ Iterator<Integer> it = arrayList.iterator(); while (it.hasNext()) { int num = it.next(); System.out.println(num); } } /** * Vector基本操作 */ public static void testVector() { System.out.println("---Vector---"); /** Vector*/ Vector<Integer> vector = new Vector<>(); System.out.println("Vector 長度: " + vector.size()); for (int i = 0; i < 5; i++) { vector.add(i); } System.out.println("Vector 長度: " + vector.size()); /** Vectort 刪除對象*/ vector.remove(3); System.out.println("Vector 長度: " + vector.size()); /** Vectort 遍歷方式 1 增強for循環, 獲得值, 無法獲得索引*/ for (Integer intNum : vector) { System.out.println(intNum); } /** Vectort 遍歷方式 2普通for循環, 值和索引都能得到*/ for (int i = 0; i < vector.size(); i++) { int num = vector.get(i); System.out.println(num); } /** Vectort 遍歷方式 3 迭代器 Itertor, 獲得值, 無法獲得索引*/ Iterator<Integer> it = vector.iterator(); while (it.hasNext()) { int num = it.next(); System.out.println(num); } } /** * Stack基本操作 */ public static void testStack() { System.out.println("---Stack---"); /** Stack*/ Stack<Integer> stack = new Stack<>(); System.out.println("Stack 長度: " + stack.size()); for (int i = 0; i < 5; i++) { /** 入棧*/ stack.push(i); } System.out.println("Stack 長度: " + stack.size()); /** Stack pop 出棧*/ stack.pop(); System.out.println("Stack 長度: " + stack.size()); /** Stack peek 得到棧頂的元素*/ int peekNum = stack.peek(); System.out.println("Stack peekNum: " + peekNum); /** Stack search 檢測一個元素在堆棧中的位置*/ int pos = stack.search(3); System.out.println("Stack search pos: " + pos); /** Stack 遍歷方式 1 增強for循環*/ for (Integer intNum : stack) { System.out.println(intNum); } } /** * HashMap基本操作 */ public static void testHashMap() { System.out.println("---HashMap---"); HashMap<Integer, Integer> hashMap = new HashMap<>(); System.out.println("HashMap 長度: " + hashMap.size()); for (int i = 0; i < 5; i++) { /** HashMap 添加對象*/ hashMap.put(i, 100 + i); } System.out.println("HashMap 長度: " + hashMap.size()); /** HashMap 刪除對象*/ hashMap.remove(2); System.out.println("HashMap 長度: " + hashMap.size()); /** HashMap 遍歷方式 1 增強for循環遍歷 Entry */ System.out.println("HashMap 遍歷方式 1 增強for循環遍歷 Entry "); for (Map.Entry<Integer, Integer> entry : hashMap.entrySet()) { System.out.println("hashMap key: " + entry.getKey() + " hashMap value: " + entry.getValue()); } /** HashMap 遍歷方式 2 通過迭代器遍歷 key */ System.out.println("HashMap 遍歷方式 2 通過迭代器遍歷 key *"); Iterator<Integer> it0 = hashMap.keySet().iterator(); while (it0.hasNext()) { int key = it0.next(); int value = hashMap.get(key); System.out.println("key: " + key + " value: " + value); } /** HashMap 遍歷方式 3 通過 增強for循環遍歷 key*/ System.out.println("HashMap 遍歷方式 3 通過 增強for循環遍歷 key"); for (Integer key : hashMap.keySet()) { int value = hashMap.get(key); System.out.println("key: " + key + " value: " + value); } /** HashMap 遍歷方式 4 通過迭代器遍歷 values, 無法得到 key值 */ System.out.println("HashMap 遍歷方式 4 通過迭代器遍歷 values, 無法得到 key值 "); Iterator<Integer> it1 = hashMap.values().iterator(); while (it1.hasNext()) { int value = it1.next(); System.out.println("value: " + value); } /** HashMap 遍歷方式 5 通過 增強for循環遍歷 values, 無法得到 key值 */ System.out.println("HashMap 遍歷方式 5 通過 增強for循環遍歷 values, 無法得到 key值 "); for (Integer value : hashMap.values()) { System.out.println("value: " + value); } } /** * HashSet基本操作 */ public static void testHashSet() { System.out.println("---HashSet---"); HashSet<Integer> hashSet = new HashSet<>(); System.out.println("HashSet 長度: " + hashSet.size()); /** 循環兩次,放入重複的1-5*/ for (int i = 0; i < 5; i++) { hashSet.add(i); } for (int i = 0; i < 5; i++) { hashSet.add(i); } System.out.println("HashSet 長度: " + hashSet.size()); /** HashSet 遍歷方式 1 增強for循環*/ for (Integer intNum : hashSet) { System.out.println(intNum); } }}
輸出:
---ArrayList--- ArrayList 長度: 0 ArrayList 長度: 5 ArrayList 長度: 4 0 1 2 4 0 1 2 4 0 1 2 4 ---Vector--- Vector 長度: 0 Vector 長度: 5 Vector 長度: 4 0 1 2 4 0 1 2 4 0 1 2 4 ---Stack--- Stack 長度: 0 Stack 長度: 5 Stack 長度: 4 Stack peekNum: 3 Stack search pos: 1 0 1 2 3 ---HashMap--- HashMap 長度: 0 HashMap 長度: 5 HashMap 長度: 4 HashMap 遍歷方式 1 增強for循環遍歷 Entry hashMap key: 0 hashMap value: 100 hashMap key: 1 hashMap value: 101 hashMap key: 3 hashMap value: 103 hashMap key: 4 hashMap value: 104 HashMap 遍歷方式 2 通過迭代器遍歷 key * key: 0 value: 100 key: 1 value: 101 key: 3 value: 103 key: 4 value: 104 HashMap 遍歷方式 3 通過 增強for循環遍歷 key key: 0 value: 100 key: 1 value: 101 key: 3 value: 103 key: 4 value: 104 HashMap 遍歷方式 4 通過迭代器遍歷 values, 無法得到 key值 value: 100 value: 101 value: 103 value: 104 HashMap 遍歷方式 5 通過 增強for循環遍歷 values, 無法得到 key值 value: 100 value: 101 value: 103 value: 104 ---HashSet--- HashSet 長度: 0 HashSet 長度: 5 0 1 2 3 4
④ FAQ
集合類相關常見問題
1.集合類和數組的區別
數組(可以存儲基本數據類型)是用來存現對象的一種容器, 數組的長度固定, 適合在對象數量固定時使用.
集合(只能存儲對象,對象類型可以不一樣)的長度可變,可在對象數量不固定時使用.
2.ArrayList
和LinkedList
區別
ArrayList
和LinkedList
在用法上沒有區別,但是在功能上還是有區別的.LinkedList
經常用在增刪操作較多而查詢操作很少的情況下, 比如隊列和堆棧.ArrayList
則相反.ArrayList底層是Object數組,所以ArrayList具有數組的查詢速度快的優點以及增刪速度慢的缺點. 而在LinkedList的底層是一種雙向循環鏈表.在此鏈表上每一個數據節點都由三部分組成:前指針(指向前面的節點的位置),數據,後指針(指向後面的節點的位置).最後一個節點的後指針指向第一個節點的前指針,形成一個循環.雙向循環鏈表的查詢效率低但是增刪效率高.
對於隨機訪問get和set,ArrayList覺得優於LinkedList,因爲LinkedList要移動指針.
對於新增和刪除操作add和remove,LinedList比較佔優勢,因爲ArrayList要移動數據.
ArrayList和LinkedList應用場景
若只對單條數據插入或刪除,ArrayList的速度優於LinkedList. 但若是批量隨機的插入刪除數據,LinkedList的速度大大優於ArrayList. 因爲ArrayList每插入一條數據,要移動插入點及之後的所有數據.
隊列和棧
隊列:先進先出的數據結構.
棧:後進先出的數據結構.
使用棧的時候, 不能提供非末尾元素出棧的方法.
3.HashTable
與HashMap
區別
Hashtable
是基於陳舊的Dictionary
類的,HashMap
是Java 1.2引入的Map
接口的一個實現Hashtable
是線程安全的,也就是說是同步的, 而HashMap
是線程序不安全的,不是同步的HashMap·允許存在一個爲空(null)的
key,多個爲空(null)的
value`.Hashtable
的key
和value
都不允許爲空(null).
4.ArrayList
和Vector
區別
Vector
是線程同步的,所以它也是線程安全的. 而Arraylist
不是線程同步的. 如果不考慮到線程的安全因素,一般用Arraylist
效率比較高.如果集合中的元素的數目大於目前集合數組的長度時,
Vector
增長率爲目前數組長度的100%
, 而Arraylist
增長率爲目前數組長度的50%
. 在集合中使用數據量比較大的數據,用Vector
有一定的優勢.如果查找一個指定位置的數據,
Vector
和Arraylist
使用的時間是相同的,都是O(1)
, 這個時候使用Vector
和Arraylist
都可以.
5.ArrayList
和Linklist
區別
ArrayList
和Vector
是採用數組方式存儲數據, 此數組元素數大於實際存儲的數據以便增加和插入元素, 都允許直接序號索引元素, 但是插入數據要設計到數組元素移動等內存操作, 所以索引數據快插入數據慢.Vector
由於使用了synchronized
方法(線程安全)所以性能上比ArrayList
要差.LinkedList
使用雙向鏈表實現存儲, 按序號索引數據需要進行向前或向後遍歷, 但是插入數據時只需要記錄本項的前後項即可,所以插入數度較快!如果移動一個指定位置的數據花費的時間爲
O(n-i)
,n
爲總長度, 這個時候就應該考慮到使用Linklist
, 因爲它移動一個指定位置的數據所花費的時間爲O(1)
, 而查詢一個指定位置的數據時花費的時間爲O(i)
.
6.HashMap
與TreeMap
區別
TreeMap
實現SortedMap
, 元素順序固定.HashMap
沒有實現該接口.HashMap
通過hashcode
對其內容進行快速查找,HashMap
中元素的排列順序是不固定的, 而TreeMap
中所有的元素都保持着某種固定的順序. 如果需要得到一個有序的結果應該使用TreeMap
.在
Map
中插入、刪除和定位元素,HashMap
是最好的選擇. 但如果要按自然順序或自定義順序遍歷鍵, 那麼TreeMap
會更好.使用
HashMap
要求添加的鍵類明確定義了hashCode()
和equals()
的實現. 這個TreeMap
沒有調優選項, 因爲該樹總處於平衡狀態.
⑤ 相關文章