Map接口特点
- Map与Collection并列存在,用于保存具有映射关系的数据:Key-Value(双列元素)
- Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中
- Map中的key不允许重复,原因和HashSet一样
- Map中的value可以重复
- Map中的key可以为null,value也可以为null;但是key只有一个为null,而value为null则可以有多个
- 常用String类作为Map的key
- key和value之间存在单向一对一关系,即通过指定的key总能找到对应的value
- Map的一对key-value是存放在一个Node中的,又因为Node实现了Entry接口,也有一种说法是一对key-value就是一个Entry
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
}
可以看到Node中包含key和value属性
具体解读:
- k-v最后是HashSet$Node node = newNode(hash, key, value, null);
- k-v为了方便程序员的遍历,还会创建EntrySet集合,该集合存放的类型元素为Entry,而一个Entry对象里就有k,v EntrySet<Entry<k,v>>,即transient Set<Map.Entry<k,v>> entrySet;
- 真正的key和value 是存放在node中,而set和collection里存的 只是指向node的 内存地址,为了方便去遍历 而提供了set和collection。
- 当把 HashMap$Node 对象 存放到entrySet 就方便了我们遍历,因为Map.Entry提供了重要方法 K getKey(); V getValue();
实现类HashMap
- 如果添加相同的key,则会覆盖原来的key-val,等同于修改。(key不会被替换,val会替换)
- 与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的。
- HashMap没有实现同步,因此线程不安全的
实现类HashTable
特性:
- HashTable的键值对都不能为null
- 使用方法和HashMap基本上一样
- HashTable是线程安全的
扩容机制:
- 底层有数组HashTable$Entry[ ] 初始化大小为11
2. 临界值 threshold 值为8 = 11 * 0.75
3. 扩容:按照自己的扩容机制来进行即可
4. 执行 方法addEntry(hash, key, value, index) ; 添加K-V 封装到Entry
5. 当 if (count >= threshold) 满足时,就进行扩容
6. 按照 int newCapacity = (oldCapacity << 1) + 1 ; 的大小扩容