"HashMap是Java中常用的集合类之一,它基于哈希表的实现,提供了高效的插入、删除和查找操作。HashMap内部使用了一个数组(数组的每个元素是Node类型,Node是HashMap的基本存储单元,包含键值对key-value)结合链表和红黑树的数据结构。初始容量为16,并且在需要时会自动扩容。HashMap的核心操作`put(key, value)`首先通过`hash(key)`计算key的哈希值,然后利用位与运算`(length - 1) & hash`确定元素在数组中的位置(index)。如果多个元素哈希到同一个索引,它们会形成链表,新插入的元素作为链表的新节点。当链表达到一定长度(默认8)时,链表会转换为红黑树,以保持查找效率。二叉查找树(BST)是一种特殊的二叉树,其中每个节点的左子树只包含小于当前节点的节点,右子树包含大于当前节点的节点,且左右子树都是平衡的。红黑树是对BST的一种优化,保证了插入和删除操作的平均时间复杂度为O(logn)。"
在HashMap中,`put`操作的过程如下:
1. 计算键key的哈希值`hash`。
2. 使用`(length - 1) & hash`得到索引`index`,将键值对放入数组`tab`的对应位置。
3. 如果数组该位置为空,直接创建一个新的Node对象插入。
4. 如果已有Node,检查是否需要形成链表或红黑树。如果形成链表,新插入的Node将成为链表的尾部。当链表长度达到8,会将链表转换为红黑树。
5. 在红黑树中插入节点时,会根据二叉查找树的规则调整树结构,以保持平衡。
HashMap的自动扩容机制确保了在元素数量增加时,仍能保持较高的性能。当数组达到其容量的75%时,HashMap会进行扩容,新容量为原来的2倍。扩容过程中,需要重新计算所有元素的索引并重新插入,这是一个相对耗时的操作,因此在预知大量元素要插入时,可以手动设置初始容量以减少扩容次数。
总结来说,HashMap通过哈希算法和数组+链表/红黑树的组合,实现了高效的数据存储和检索。其核心在于哈希函数的使用,使得大部分情况下查找时间复杂度接近O(1),而链表和红黑树的引入则解决了哈希冲突问题,保证了在冲突较多的情况下依然能维持良好的性能。