Java集合之Map

这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

Map 是 Java 中常用集合之一,其重点实现类包括 HashMap、LinkedHashMap、TreeMap 和 Hashtable

注意:Map 是集合,但并不属于 Collection。

Java集合-Map.png

HashMap

HashMap 的底层采用数组 + 链表 / 红黑树(JDK 1.8)。HashMap 键的唯一性,是通过 hashcode 来保证的,因此,若其键为实体,则需要重写 equals() 和 hashcode()。

HashMap底层.png

LinkedHashMap

LinkedHashMap 是 HashMap 的一种特殊形式,其 Entry 加入了 before 和 after,从而使其底层变为了数组 + 双向链表的形式。双向链表记录了整个 table 的顺序,因此 LinkedHashMap 是有序的

static class Entry<K,V> extends HashMap.Node<K,V> {
    Entry<K,V> before, after;
    Entry(int hash, K key, V value, Node<K,V> next) {
        super(hash, key, value, next);
    }
}
复制代码

HashMap 和 LinkedHashMap 的结构示意图如下:

LinkedHashMap结构.png

Hashtable

Hashtable 是线程安全的,但因为性能问题,已被废弃。在多线程环境中,可以使用 Collections.synchronizedMap 或者 ConcurrentHashMap,前者加锁的地方更多,因此后者的性能更好。

其它 Map

  1. IdentityHashMap 允许键值为 null,不能保证插入遍历的顺序一致。其特殊的地方是用 == 来比较 key 是否相等,而不是 equals。
  2. WeakHashMap 的 key 报错了实际对象的弱引用,因此键值对会随着实际对象的回收而自动删除,不太常用。
  3. TreeM 是非线程安全的,基于红黑树实现,因为该树总处于平衡状态,因此没有调优选项。不过可以通过重写比较器来实现自定义排序。

总结

key value 容量 扩容 有序性 父类 hashcode 说明
HashMap 允许 null 允许 null 16 2n 无序 AbstractMap 重新计算 非线程安全
LinkedHashMap 允许 null 允许 null 16 2n 有序 AbstractMap 重新计算 非线程安全
TreeMap 不允许 null 允许 null 16 2n 自然排序 AbstractMap 重新计算 非线程安全
ConcurrentHashMap 不允许 null 不允许 null 16 2n 无序 AbstractMap 重新计算 锁分段技术
Hashtable 不允许 null 不允许 null 11 2n+1 无序 Dictionary 直接使用 线程安全