Map的学习笔记
首先,我们已经完成了对List的学习,现在我们就开始学习Map
首先,我们先看看Map的架构
我们可以看到
- Map是顶级接口类,他不继承或者实现别的接口
- Map代表着键值对的形式,既Key-Value
- AbstractMap是一个抽象类,它实现了Map中的许多方法,所有想实现Map接口的都可以继承这个类
- SrotedMap是一个有序的Map,可以排序键值对,排序的方法是通过比较器
- NavigableMap相比于SortedMap,它存在一系列的导航方法,如获取大于/等于/小于某对象的键值对
- TreeMap实现了NavigableMap,很明显他是一个有序的Map
- HashMap并没有实现排序的接口,说明是Map,但不有序
- WeakHashMap,与HashMap不同的是,WeakHashMap是弱键
- HashTble是继承于Directionary,但是HashTable是线程安全的
我们先看看各个抽象类的情况
1、Map
public interface Map<K,V>
Map是一个以键值对(Key-Value)形式的数据结构,Key是唯一的,且一个Key只能对应一个Value
简单来说,在Map接口中,规定了Map到底是什么样的数据结构,第二规定了Map所提供的方法
abstract void clear()
abstract boolean containsKey(Object key)
abstract boolean containsValue(Object value)
abstract Set<Entry<K, V>> entrySet()
abstract boolean equals(Object object)
abstract V get(Object key)
abstract int hashCode()
abstract boolean isEmpty()
abstract Set<K> keySet()
abstract V put(K key, V value)
abstract void putAll(Map<? extends K, ? extends V> map)
abstract V remove(Object key)
abstract int size()
abstract Collection<V> values()
上面为一下Map常用Api
Map提供接口分别用于返回 键集、值集或键-值映射关系集。
①entrySet()用于返回键-值集的Set集合
②keySet()用于返回键集的Set集合
③values()用户返回值集的Collection集合
因为Map中不能包含重复的键;每个键最多只能映射到一个值。
所以,键-值集、键集都是Set,值集时Collection。
2、Map.Entry
简单来说Map中的Entry类就是把Map中的每一个K-V看做一个实体
abstract boolean equals(Object object)
abstract K getKey()
abstract V getValue()
abstract int hashCode()
abstract V setValue(V object)
Map.Entry的常用Api的,可以取出一个实体的的Key和Value的值
以往在遍历Map时
System.out.println("通过Map.keySet遍历key和value:");
for (String key : map.keySet()) {
System.out.println("key= "+ key + " and value= " + map.get(key));
}
因为Map没有继承Itorable接口,所以没法用迭代器遍历
所以必须要通过返回一个Key的集合,通过不断遍历这个集合的Key,通过Key再找到value
但是通过Entry的话,返回一个Entry集合
System.out.println("通过Map.entrySet使用iterator遍历key和value:");
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
只需要遍历这个Entry就可以得到全部的Map值了
3、AbstractMap
public abstract class AbstractMap<K,V> implements Map<K,V>
AbstractMap实现了Map接口中的大部分方法,只保留了1个抽象方法等待着子类去实现
public abstract Set<Entry<K,V>> entrySet();
我们首先来看一下get方法在AbstractMap中是如何实现的
public V get(Object key) {
Iterator<Entry<K,V>> i = entrySet().iterator();
if (key==null) {
while (i.hasNext()) {
Entry<K,V> e = i.next();
if (e.getKey()==null)
return e.getValue();
}
} else {
while (i.hasNext()) {
Entry<K,V> e = i.next();
if (key.equals(e.getKey()))
return e.getValue();
}
}
return null;
}
首先第一行就显示了
Iterator<Entry<K,V>> i = entrySet().iterator();
首先得到一个entrySet,再调用它的迭代器,来遍历整个Map
while (i.hasNext()) {
Entry<K,V> e = i.next();
if (e.getKey()==null)
return e.getValue();
}
其余需要查找数据的方法,都是通过entrySet来实现的
Tips
为什么entrySet().iterator()的存在的?(也就是为什么entrySet()存在迭代器?)
首先我们回到Map接口
Set<Map.Entry<K, V>> entrySet();
返回值类型是一个Set类型
public interface Set<E> extends Collection<E>
打开Set接口,可以发现Set接口是继承Collection的
public interface Collection<E> extends Iterable<E>
Collection是继承于Iterable接口的
所以entrySet()的迭代器方法是存在的
4、SortedMap
public interface SortedMap<K,V> extends Map<K,V>
上面我们提到SortedMap的接口是有序的Map接口
另外,所有SortedMap 实现类都应该提供 4 个“标准”构造方法:
(01) void(无参数)构造方法,它创建一个空的有序映射,按照键的自然顺序进行排序。
(02) 带有一个 Comparator 类型参数的构造方法,它创建一个空的有序映射,根据指定的比较器进行排序。
(03) 带有一个 Map 类型参数的构造方法,它创建一个新的有序映射,其键-值映射关系与参数相同,按照键的自然顺序进行排序。
(04) 带有一个 SortedMap 类型参数的构造方法,它创建一个新的有序映射,其键-值映射关系和排序方法与输入的有序映射相同。无法保证强制实施此建议,因为接口不能包含构造方法。
5、NavigableMap
public interface NavigableMap<K,V> extends SortedMap<K,V>
NavigableMap是继承SortedMap的一个接口,它提供了一种导航的情况
如获取大于/等于/小于某对象的键值对
/**
* Returns the least key strictly greater than the given key, or
* {@code null} if there is no such key.
*
* @param key the key
* @return the least key greater than {@code key},
* or {@code null} if there is no such key
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key is null
* and this map does not permit null keys
*/
K higherKey(K key);
其中一个heightKey()方法的JDK注释
翻译过来就是,寻找出最近一个比给定key大的key值,如果不存在的话返回null
NavigableMap的API
abstract Entry<K, V> ceilingEntry(K key)
abstract Entry<K, V> firstEntry()
abstract Entry<K, V> floorEntry(K key)
abstract Entry<K, V> higherEntry(K key)
abstract Entry<K, V> lastEntry()
abstract Entry<K, V> lowerEntry(K key)
abstract Entry<K, V> pollFirstEntry()
abstract Entry<K, V> pollLastEntry()
abstract K ceilingKey(K key)
abstract K floorKey(K key)
abstract K higherKey(K key)
abstract K lowerKey(K key)
abstract NavigableSet<K> descendingKeySet()
abstract NavigableSet<K> navigableKeySet()
abstract NavigableMap<K, V> descendingMap()
abstract NavigableMap<K, V> headMap(K toKey, boolean inclusive)
abstract SortedMap<K, V> headMap(K toKey)
abstract SortedMap<K, V> subMap(K fromKey, K toKey)
abstract NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive)
abstract SortedMap<K, V> tailMap(K fromKey)
abstract NavigableMap<K, V> tailMap(K fromKey, boolean inclusive)
6、Dictionary
Dictionary也是一个键值对的接口
public abstract class Dictionary<K,V>
Dictionary是Jdk1.0中所使用的Key-Value,现在可用Map代替,在此不做介绍