Map的学习笔记

首先,我们已经完成了对List的学习,现在我们就开始学习Map

首先,我们先看看Map的架构Map的学习笔记 - 图1

我们可以看到

  1. Map是顶级接口类,他不继承或者实现别的接口
  2. Map代表着键值对的形式,既Key-Value
  3. AbstractMap是一个抽象类,它实现了Map中的许多方法,所有想实现Map接口的都可以继承这个类
  4. SrotedMap是一个有序的Map,可以排序键值对,排序的方法是通过比较器
  5. NavigableMap相比于SortedMap,它存在一系列的导航方法,如获取大于/等于/小于某对象的键值对
  6. TreeMap实现了NavigableMap,很明显他是一个有序的Map
  7. HashMap并没有实现排序的接口,说明是Map,但不有序
  8. WeakHashMap,与HashMap不同的是,WeakHashMap是弱键
  9. HashTble是继承于Directionary,但是HashTable是线程安全的

我们先看看各个抽象类的情况

1、Map

  1. public interface Map<K,V>

Map是一个以键值对(Key-Value)形式的数据结构,Key是唯一的,且一个Key只能对应一个Value

简单来说,在Map接口中,规定了Map到底是什么样的数据结构,第二规定了Map所提供的方法

  1. abstract void clear()
  2. abstract boolean containsKey(Object key)
  3. abstract boolean containsValue(Object value)
  4. abstract Set<Entry<K, V>> entrySet()
  5. abstract boolean equals(Object object)
  6. abstract V get(Object key)
  7. abstract int hashCode()
  8. abstract boolean isEmpty()
  9. abstract Set<K> keySet()
  10. abstract V put(K key, V value)
  11. abstract void putAll(Map<? extends K, ? extends V> map)
  12. abstract V remove(Object key)
  13. abstract int size()
  14. abstract Collection<V> values()

上面为一下Map常用Api

Map提供接口分别用于返回 键集、值集或键-值映射关系集。
①entrySet()用于返回键-值集Set集合
②keySet()用于返回键集Set集合
③values()用户返回值集Collection集合
因为Map中不能包含重复的键;每个键最多只能映射到一个值。

所以,键-值集、键集都是Set,值集时Collection

2、Map.Entry

简单来说Map中的Entry类就是把Map中的每一个K-V看做一个实体

  1. abstract boolean equals(Object object)
  2. abstract K getKey()
  3. abstract V getValue()
  4. abstract int hashCode()
  5. abstract V setValue(V object)

Map.Entry的常用Api的,可以取出一个实体的的Key和Value的值

以往在遍历Map时

  1. System.out.println("通过Map.keySet遍历key和value:");
  2. for (String key : map.keySet()) {
  3. System.out.println("key= "+ key + " and value= " + map.get(key));
  4. }

因为Map没有继承Itorable接口,所以没法用迭代器遍历

所以必须要通过返回一个Key的集合,通过不断遍历这个集合的Key,通过Key再找到value

但是通过Entry的话,返回一个Entry集合

  1. System.out.println("通过Map.entrySet使用iterator遍历key和value:");
  2. Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
  3. while (it.hasNext()) {
  4. Map.Entry<String, String> entry = it.next();
  5. System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
  6. }

只需要遍历这个Entry就可以得到全部的Map值了

3、AbstractMap

  1. public abstract class AbstractMap<K,V> implements Map<K,V>

AbstractMap实现了Map接口中的大部分方法,只保留了1个抽象方法等待着子类去实现

  1. public abstract Set<Entry<K,V>> entrySet();

我们首先来看一下get方法在AbstractMap中是如何实现的

  1. public V get(Object key) {
  2. Iterator<Entry<K,V>> i = entrySet().iterator();
  3. if (key==null) {
  4. while (i.hasNext()) {
  5. Entry<K,V> e = i.next();
  6. if (e.getKey()==null)
  7. return e.getValue();
  8. }
  9. } else {
  10. while (i.hasNext()) {
  11. Entry<K,V> e = i.next();
  12. if (key.equals(e.getKey()))
  13. return e.getValue();
  14. }
  15. }
  16. return null;
  17. }

首先第一行就显示了

Iterator<Entry<K,V>> i = entrySet().iterator();

首先得到一个entrySet,再调用它的迭代器,来遍历整个Map

  1. while (i.hasNext()) {
  2. Entry<K,V> e = i.next();
  3. if (e.getKey()==null)
  4. return e.getValue();
  5. }

其余需要查找数据的方法,都是通过entrySet来实现的

Tips

为什么entrySet().iterator()的存在的?(也就是为什么entrySet()存在迭代器?)

首先我们回到Map接口

  1. Set<Map.Entry<K, V>> entrySet();

返回值类型是一个Set类型

  1. public interface Set<E> extends Collection<E>

打开Set接口,可以发现Set接口是继承Collection的

  1. public interface Collection<E> extends Iterable<E>

Collection是继承于Iterable接口的

所以entrySet()的迭代器方法是存在的

4、SortedMap

  1. public interface SortedMap<K,V> extends Map<K,V>

上面我们提到SortedMap的接口是有序的Map接口

另外,所有SortedMap 实现类都应该提供 4 个“标准”构造方法:
(01) void(无参数)构造方法,它创建一个空的有序映射,按照键的自然顺序进行排序。
(02) 带有一个 Comparator 类型参数的构造方法,它创建一个空的有序映射,根据指定的比较器进行排序。
(03) 带有一个 Map 类型参数的构造方法,它创建一个新的有序映射,其键-值映射关系与参数相同,按照键的自然顺序进行排序。
(04) 带有一个 SortedMap 类型参数的构造方法,它创建一个新的有序映射,其键-值映射关系和排序方法与输入的有序映射相同。无法保证强制实施此建议,因为接口不能包含构造方法。

5、NavigableMap

  1. public interface NavigableMap<K,V> extends SortedMap<K,V>

NavigableMap是继承SortedMap的一个接口,它提供了一种导航的情况

如获取大于/等于/小于某对象的键值对

  1. /**
  2. * Returns the least key strictly greater than the given key, or
  3. * {@code null} if there is no such key.
  4. *
  5. * @param key the key
  6. * @return the least key greater than {@code key},
  7. * or {@code null} if there is no such key
  8. * @throws ClassCastException if the specified key cannot be compared
  9. * with the keys currently in the map
  10. * @throws NullPointerException if the specified key is null
  11. * and this map does not permit null keys
  12. */
  13. K higherKey(K key);

其中一个heightKey()方法的JDK注释

翻译过来就是,寻找出最近一个比给定key大的key值,如果不存在的话返回null

NavigableMap的API

  1. abstract Entry<K, V> ceilingEntry(K key)
  2. abstract Entry<K, V> firstEntry()
  3. abstract Entry<K, V> floorEntry(K key)
  4. abstract Entry<K, V> higherEntry(K key)
  5. abstract Entry<K, V> lastEntry()
  6. abstract Entry<K, V> lowerEntry(K key)
  7. abstract Entry<K, V> pollFirstEntry()
  8. abstract Entry<K, V> pollLastEntry()
  9. abstract K ceilingKey(K key)
  10. abstract K floorKey(K key)
  11. abstract K higherKey(K key)
  12. abstract K lowerKey(K key)
  13. abstract NavigableSet<K> descendingKeySet()
  14. abstract NavigableSet<K> navigableKeySet()
  15. abstract NavigableMap<K, V> descendingMap()
  16. abstract NavigableMap<K, V> headMap(K toKey, boolean inclusive)
  17. abstract SortedMap<K, V> headMap(K toKey)
  18. abstract SortedMap<K, V> subMap(K fromKey, K toKey)
  19. abstract NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive)
  20. abstract SortedMap<K, V> tailMap(K fromKey)
  21. abstract NavigableMap<K, V> tailMap(K fromKey, boolean inclusive)

6、Dictionary

Dictionary也是一个键值对的接口

  1. public abstract class Dictionary<K,V>

Dictionary是Jdk1.0中所使用的Key-Value,现在可用Map代替,在此不做介绍