private static class Entry<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Entry<K,V> next;
protected Entry(int hash, K key, V value, Entry<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
@SuppressWarnings("unchecked")
protected Object clone() {
return new Entry<>(hash, key, value,
(next==null ? null : (Entry<K,V>) next.clone()));
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
public V setValue(V value) {
if (value == null)
throw new NullPointerException();
V oldValue = this.value;
this.value = value;
return oldValue;
}
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
return (key==null ? e.getKey()==null : key.equals(e.getKey())) &&
(value==null ? e.getValue()==null : value.equals(e.getValue()));
}
Map<K,V>的接口
Map
的接口中
K
代表
Key
的类型,
V
代表值的类型。
Map
和容器非常的像,需要实现一些集合中也存在的接口函数。比如说:
int size()
boolean isEmpty()
void clear()
另外,
Map
中提供了三种提取容器的方法:
Collection<V> values()
将值提取为容器。
Set<K> keySet()
将
Key
提取为集合。
Set<Map.Entry<K, V>> entrySet()
将
Entry
提取为集合。
上面三种方法体现的是映射的三要素。
KeySet
是原集合,
values
是目标集合
,Entry
是关联关系。
最后我们来看一下
Map
几个最重要的用途。
boolean containsKey(Object key)
查找
map
中有没有某个键。
boolean containsValue(Object value)
查找
map
中有没有某个
value
。
V get(Object key)
根据某一个键拿到
value
。
V put(K key, V value)
写入一组
Key
到
value
的映射关系。
V remove(Object key)
相当于
get
和删除的结合体,拿到值删除关系。
还有批量操作
:
void putAll(Map<? extends K, ? extends V> m)
这里是批量添加。
Map的实现
Map
的诸多实现中有:
ConcurrentHashMap, ConcurrentSkipListMap, EnumMap, HashMap,
Hashtable, LinkedHashMap, Properties, TreeMap,
和集合类似
Map
最常的种实现如下:
ConcurrentHashMap
,
HashMap
、
Hashtable
、
LinkedHashMap
是基于哈希表的实现
- TreeMap是基于树的实现
- ConcurrentSkipListMap是基于跳表的实现
- EnumMap是基于位运算的实现
和集合类似,哈希表的实现是一种稀疏的结构。树的实现是一种紧密的结构。树的实现中间继承
路径中会实现
NavigableMap<K,V>
,从而实现浏览的能力。
HashMap vs Hashtable
上面诸多实现当中
HashMap
和
Hashtable
实现非常相近。这里有
2
个显著的区别:
Hashtable
中的所有对用户的方法都用
synchronized
关键字上了锁(因此线程安全)。如果
你学到了本课程后续的并发编程环节。你会知道这并不是一种好的实现方案。
HashMap
没
有做任何控制。
- HashMap允许null key/null value;
- Hashtable不允许null key/null value
总结
Java
的数据结构。但是归根结底,其实只有两类。一类就是存储数据的容器 (Collection<T>)
。
一类就是将数据映射到另一种数据的
Map<K, V>
。
Map
中依然要用到容器,用 到Iterable
。但
Map
的本质不是容器,而是映射。
这些数据结构。我觉得大家可以从两方面去掌握。一方面就是什么东西是什么。比如说
HashMap
是
Hash
实现的
Map
,
TreeSet
是
Tree
实现的
Set。
另一个需要掌握的维度就是数据结构和算法本身。
TreeSet
是二叉搜索树中的红黑树,
HashMap
是哈希表,
ConcurrentSkipListMap
是跳表,
EnumSet是位运算。