Map接口

双列集合 Map - 图1

Map:存储键值对 Hash表解释:其中有0~15共16个位置,hashCode的值就是代表哈希表16个位置中的其中一个,具体的值是通过hash函数计算出来的,hashCode的存在就是为了能在散列存储结构中快速查找对象。

1.Hashtable注意table,[数组+链表]

线程安全,性能低

Hashtable 初始容量为:11

HashTable 使用一把锁(锁住整个链表结构)处理并发问题,多个线程竞争一把锁,容易阻塞;

2.HashMap[数组 + 链表/红黑树]

异步处理,非线程安全,性能高
默认null,懒加载后容量为16(数组),扩容因子为0.75
HashMap有快速寻址的特点
HashMap不能保证元素的顺序

使用场景:在 Map 中插入、删除和定位元素时;
key重复值将被覆盖

  • jdk1.8 当每个链表长度 >8 ,并且数组元素个数 ≥64时,会调整成红黑树,目的是提高效率
  • jdk1.8 当链表长度 <6 时 调整成链表
  • jdk1.8 以前,链表时头插入,之后为尾插入

2.1 ConcurrentHashMap 多线程中使用

对桶数组进行分段加锁,不允许空值.
是HashMap的线程安全版(自JDK1.5引入),提供比Hashtable更高效的并发性能。
原理:
ConcurrentHashMap使用分离锁的思路解决并发性能,其将 Entry数组拆
分至16个Segment中,以哈希算法决定Entry应该存储在哪个Segment。
这样就可以实现在写操作时只对一个Segment 加锁,大幅提升了并发写的性能。
在进行读操作时,ConcurrentHashMap在绝大部分情况下都不需要加锁,其Entry
中的value是volatile的,这保证了value被修改时的线程可见性,无需加锁便能实现
线程安全的读操作。
它不能保证读操作的绝对一致性。

2.2 WeakHashMap

2.3 LinkedHashMap

  • 优于HashMap
  • 和HashMap相比存慢取快
  • 遍历比 HashMap 慢;
  • LinkedHashMap 保存了记录的插入顺序;

LinkedHashMap与HashMap非常类似,唯一的不同在于前者
的Entry在HashMap.Entry的基础上增加了到前一个插入和后一个插入的Entry的引用,以实现能够按Entry的插入顺序进行遍历。

双列集合 Map - 图2
LinkedHashMap中也实现了Lru算法
image.png

使用场景: 在需要输出的顺序和输入的顺序相同的情况下。

3. SortedMap

3.1 TreeMap

TreeMap是基于红黑树实现的Map结构,其Entry类拥有到左/右叶子节点和父节点的引用,同时还记录了自己的颜色
能够把它保存的记录根据键排序(默认按键值升序排序,也可以指定排序的比较器)

使用场景: 在需要按自然顺序或自定义顺序遍历键的情况下;

关于map的空值问题

双列集合 Map - 图4

且两者的的key值均不能重复,若添加key相同的键值对,后面的value会自动覆盖前面的value,但不会报错。

  • ConcurrentHashMap放入null值报错
  1. //ConcurrentHashMap源码:
  2. /** Implementation for put and putIfAbsent */
  3. final V putVal(K key, V value, boolean onlyIfAbsent) {
  4. if (key == null || value == null) throw new NullPointerException();
  5. //......

Map常用方法

isEmpty, clear, remove, containsKey/Value
replace(1.8). putIfAbsent(存在则不更新)
getIfDefault(没获取到取默认值)