Java 的 HashMap 是一个常用的基于哈希表的数据结构,它实现了 Map 接口,可以存储键值对。下面我们进行详细介绍:
-
基本结构:HashMap 底层是基于哈希表来实现的,每次插入一个键值对时,会先对该键进行 Hash 运算,然后将值保存在对应的索引位置上,这个索引就是通过哈希函数计算出来的。
-
线程安全:HashMap 是非线程安全的,多个线程同时对 HashMap 进行读写操作可能会导致数据的不一致性。如果要在多线程环境中使用 Map,可以使用 ConcurrentHashMap 或者在对 HashMap 进行操作时手动加锁。
-
扩容机制:HashMap 内部有一个默认的负载因子(load factor)值为 0.75,当 HashMap 中的元素数量超过负载因子与容量(capacity)的积时,就需要进行扩容,容量会扩大一倍。扩容操作会导致哈希表进行重建,所有的键值对需要重新计算哈希值,并且重新分配数组大小。因此,扩容操作对性能有一定的影响,应该尽量避免赋值操作导致 HashMap 频繁扩容。
-
内部实现:HashMap 的实现逻辑基于数组和单向链表,每个数组元素都是一个链表的头节点,当发生 Hash 冲突时,新插入的键值对会添加到对应元素的链表中。在 JDK8 中,HashMap 通过链表长度阈值和红黑树两种结构进行优化,当链表长度超过 8 时,会将其转化为红黑树,加快查询速度。在 JDK9 中,HashMap 对链表的处理进行了更改,引入了一个新节点类型-Node,用于兼容红黑树节点和链表节点。