哈希冲突是指在哈希表中,两个或更多个不同的键被映射到了同一个哈希桶的情况。这种情况可能会导致数据丢失或者检索效率下降,因为不同的键被映射到了同一个位置,需要额外的操作来处理这种冲突。
解决哈希冲突的常见方法包括:
-
开放寻址法:当发生冲突时,继续寻找下一个可用的位置,直到找到空闲的位置为止。这种方法可能会导致聚集(clustering)现象,即冲突位置附近的空间被更频繁地使用。
-
链地址法(Chaining):在哈希表的每个位置维护一个链表(或者其他数据结构),将具有相同哈希值的键值对存储在同一个链表中。当发生冲突时,新的键值对被添加到对应位置的链表中。这种方法需要额外的内存来存储链表,但可以避免聚集现象。
-
再哈希法:当发生冲突时,使用另一个哈希函数对键进行再次哈希,以确定下一个位置。这种方法需要选择一个合适的再哈希函数,以避免过多的冲突。
-
建立更复杂的数据结构:例如,使用平衡二叉树或者跳表等数据结构来解决冲突,这些数据结构能够保持较高的检索效率,并且能够处理冲突。
hsahmap是如何处理hash冲突的
当我们向 HashMap 中插入键值对时,首先通过哈希函数计算键的哈希值,然后将键值对存储在对应的哈希桶中。如果发生了哈希冲突,也就是两个不同的键具有相同的哈希值,则采用链地址法:在哈希桶中的位置上维护一个链表(Java 8 之后可能是红黑树),将具有相同哈希值的键值对按顺序存储在链表中。当发生冲突时,新的键值对会被添加到对应位置的链表的末尾。
HashMap 在实现中会监控链表的长度,当链表长度超过一定阈值(Java 8 中默认为8),就会将链表转化为红黑树,以提高检索效率。这种自适应的数据结构选择能够在处理大量数据时保持较高的性能。
在 Java 8 之前,HashMap 采用的是数组 + 链表的方式来处理冲突;在 Java 8 引入了红黑树来优化链表过长的情况,进一步提高了 HashMap 的性能