前言
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是线程安全的,但是性能比较差。