前言
Java集合框架主要分成Collection體系和Map體系,Collection主要存儲單列數據,而Map則是存儲鍵值對格式的數據,key相當於是value的索引,key不可以重複,但是value是可以重複的。
和Collection一樣,Map接口也有很多類型的子類和實現類,圖譜如下圖示:
Map體系的頂級接口就是Map接口,Map接口基本上定義了Map操作相關的所有方法,常用方法分別如下:
1 public interface Map<K,V> { 2 /** 返回Map的數據個數 */ 3 int size(); 4 5 /** 判斷Map是否爲空 */ 6 boolean isEmpty(); 7 8 /** 判斷Map是否包含某個key */ 9 boolean containsKey(Object key); 10 11 /** 判斷Map是否包含某個value */ 12 boolean containsValue(Object value); 13 14 /** 根據key獲取對應的value*/ 15 V get(Object key); 16 17 /** 插入<key,value>鍵值對*/ 18 V put(K key, V value); 19 20 /** 插入Map對象*/ 21 void putAll(Map<? extends K, ? extends V> m); 22 23 /** 移除指定的key */ 24 V remove(Object key); 25 26 /** 清空整個Map*/ 27 void clear(); 28 29 /** 返回Map所有的key,由於不會重複所以用Set*/ 30 Set<K> keySet(); 31 32 /** 返回Map所有的value,由於會重複所以用Collection*/ 33 Collection<V> values(); 34 35 /** 返回Map所有的<key,value>,由於不會重複,所以用Set*/ 36 Set<Map.Entry<K, V>> entrySet(); 37 }
除了定義了基本的操作方法之外,Map內部還有一個內部接口Entry,此接口表示一組<key,value>對象,代碼如下:
1 interface Entry<K,V> { 2 3 /** 返回key */ 4 K getKey(); 5 6 /** 返回value */ 7 V getValue(); 8 9 /** 設置value */ 10 V setValue(V value); 11 12 /** 比較對象是否相等*/ 13 boolean equals(Object o); 14 15 /** 16 * 計算hashCode 17 */ 18 int hashCode(); 19 }
Map接口有一個抽象實現類AbstractMap實現了Map通用的基本方法,並且通過模板方法設計模式通過調用子類實現的抽象方法來實現了Map的方法,代碼如下:
1 /** 實現size方法 */ 2 public int size() { 3 /** 返回entrySet方法的Set的大小*/ 4 return entrySet().size(); 5 } 6 7 /** 抽象方法需要子類實現, 返回Set<Entry<key,value>>*/ 8 public abstract Set<Entry<K,V>> entrySet(); 9 10 /** 實現size方法*/ 11 public boolean isEmpty() { 12 /** 判斷size方法的值是否爲0 */ 13 return size() == 0; 14 } 15 16 /** 實現了containsValue方法*/ 17 public boolean containsValue(Object value) { 18 /** 遍歷entrySet返回的Set,通過迭代器遍歷判斷是否值和value相等*/ 19 Iterator<Entry<K,V>> i = entrySet().iterator(); 20 if (value==null) { 21 while (i.hasNext()) { 22 Entry<K,V> e = i.next(); 23 if (e.getValue()==null) 24 return true; 25 } 26 } else { 27 while (i.hasNext()) { 28 Entry<K,V> e = i.next(); 29 if (value.equals(e.getValue())) 30 return true; 31 } 32 } 33 return false; 34 } 35 36 /** 實現了containKey方法*/ 37 public boolean containsKey(Object key) { 38 /** 原理同上 */ 39 Iterator<Map.Entry<K,V>> i = entrySet().iterator(); 40 if (key==null) { 41 while (i.hasNext()) { 42 Entry<K,V> e = i.next(); 43 if (e.getKey()==null) 44 return true; 45 } 46 } else { 47 while (i.hasNext()) { 48 Entry<K,V> e = i.next(); 49 if (key.equals(e.getKey())) 50 return true; 51 } 52 } 53 return false; 54 } 55 56 /** 實現了get方法 */ 57 public V get(Object key) { 58 /** 原理同上,遍歷所有entry,返回key和參數相等的value*/ 59 Iterator<Entry<K,V>> i = entrySet().iterator(); 60 if (key==null) { 61 while (i.hasNext()) { 62 Entry<K,V> e = i.next(); 63 if (e.getKey()==null) 64 return e.getValue(); 65 } 66 } else { 67 while (i.hasNext()) { 68 Entry<K,V> e = i.next(); 69 if (key.equals(e.getKey())) 70 return e.getValue(); 71 } 72 } 73 return null; 74 } 75 76 /** 實現了put方法*/ 77 public V put(K key, V value) { 78 /** 直接拋異常,需要子類實現具體的put邏輯*/ 79 throw new UnsupportedOperationException(); 80 } 81 82 /** 實現了remove方法*/ 83 public V remove(Object key) { 84 Iterator<Entry<K,V>> i = entrySet().iterator(); 85 Entry<K,V> correctEntry = null; 86 if (key==null) { 87 while (correctEntry==null && i.hasNext()) { 88 Entry<K,V> e = i.next(); 89 if (e.getKey()==null) 90 correctEntry = e; 91 } 92 } else { 93 while (correctEntry==null && i.hasNext()) { 94 Entry<K,V> e = i.next(); 95 if (key.equals(e.getKey())) 96 correctEntry = e; 97 } 98 } 99 100 V oldValue = null; 101 if (correctEntry !=null) { 102 oldValue = correctEntry.getValue(); 103 i.remove(); 104 } 105 return oldValue; 106 }
Map接口除了有一個抽象的實現類AbstractMap之外,還有兩個子接口,分別是有序集合SortedMap和併發集合ConcurrentMap
SortetMap繼承之Map接口,除了定義了基本的Map操作方法之外,還額外定義了和排序相關的方法,分別如下:
1 public interface SortedMap<K,V> extends Map<K,V> { 2 3 /** 返回排序執行器,具體的排序規則由Comparator實現 */ 4 Comparator<? super K> comparator(); 5 6 /** 返回指定區間之內的子集合,相當於截取了fromKey到toKey之間的Map*/ 7 SortedMap<K,V> subMap(K fromKey, K toKey); 8 9 /** 返回從第一個key到toKey之間的子集合*/ 10 SortedMap<K,V> headMap(K toKey); 11 12 /** 返回從fromKey到最後一個key之間到子集合*/ 13 SortedMap<K,V> tailMap(K fromKey); 14 15 /** 返回第一個key*/ 16 K firstKey(); 17 18 /** 返回最後一個key*/ 19 K lastKey(); 20 21 /** 返回所有key的Set集合*/ 22 Set<K> keySet(); 23 24 /** 返回所有value的集合*/ 25 Collection<V> values(); 26 27 /** 返回所有<key,value>的Set集合*/ 28 Set<Map.Entry<K, V>> entrySet(); 29 }
ConcurrentMap同樣繼承之Map接口,該接口是在Map的基礎上同步操作的相關方法,主要是在操作之前判斷當前值是否存在或者判斷當前值是否和期望的值相等,常用方法如下:
1 public interface ConcurrentMap<K, V> extends Map<K, V> { 2 3 /** 根據key獲取value,如果不存在則返回一個默認值*/ 4 @Override 5 default V getOrDefault(Object key, V defaultValue) { 6 V v; 7 return ((v = get(key)) != null) ? v : defaultValue; 8 } 9 10 /** 如果key不存在則插入<key,value> */ 11 V putIfAbsent(K key, V value); 12 13 /** 當指定key的值和傳入的value值相等時,則移除此key */ 14 boolean remove(Object key, Object value); 15 16 /** 當指定key的值爲oldValue值時,則替換成newValue*/ 17 boolean replace(K key, V oldValue, V newValue); 18 19 /** 當指定key存在時,則將當前值替換成value*/ 20 V replace(K key, V value); 21 }
AbstactMap、SortetMap、ConcurrentMap這三個是直接繼承或者是實現了Map接口,但是隻能算是個半成品,所以具體場景還是會用到其他具體的Map實現,比如常用的HashTable、HashMap、TreeMap、ConcurrentHashMap等等。
具體Map的實現類的源碼解析參加文章 Java集合框架整理6--Map體系HashMap、TreeMap、ConcurrentHashMap、ConcurrentSkipListMap源碼解析
而HashTable底層實現和HashMap實現原理基本上一致,只不過HashTable等所有提供的方法都通過Synchronzied修飾,所以HashTable是線程安全的,但是性能比較差。