导航
-
- 一. 简介
- 二. 解决Hash冲突的方法
-
- 1. 开放地址法
-
- 1.1 线性探测再散列
- 1.2 二次探测再散列
- 1.3 伪随机探测再散列
- 2. 链地址法
- 3. 再哈希法
一. 简介
哈希(hash)是将任意长度的输入数据转化为固定长度的输出数据的算法。哈希函数会将输入数据压缩并映射为一个固定长度的哈希值,通常用一个字符串或数字来表示。
哈希冲突是指两个不同的输入值在经过哈希函数计算后得到了相同的哈希值。由于哈希函数的输出长度是固定的,而输入的数据可能有无限多的可能性,所以哈希冲突是不可避免的。
哈希冲突会引起一些问题,例如当使用哈希表进行数据存储时,如果有两个不同的键经过哈希函数计算得到了相同的哈希值,就会导致数据冲突,可能会导致数据丢失或覆盖。
二. 解决Hash冲突的方法
1. 开放地址法
当发生冲突时,继续寻找哈希表中的下一个空槽位,直到找到一个空槽位为止
1.1 线性探测再散列
当发生哈希冲突时,即两个不同的元素被哈希到了同一个槽位上,会依次向后探测下一个可用的槽位,直到找到一个空槽位或者遍历完整个哈希表。ThreadLocalMap 就是使用的线性探测再散列方法来解决Hash冲突的。
- 具体步骤:
根据哈希函数,将要插入的元素散列到哈希表的一个槽位
如果该槽位已经被占用,就继续向下一个槽位探测,直到找到一个空槽位。
如果遍历完整个哈希表仍然没有找到空槽位,就表示哈希表已满。 - 缺点
容易引起聚集,即当哈希表中有一部分槽位被占用时,会导致后续的插入操作耗时增加。此外,删除操作也会导致问题,因为删除一个元素后,后续的插入操作就无法正确地找到原本的位置了 - 优点
实现简单,易于理解和实现
private static final int TABLE_SIZE = 10;
private static class HashEntry {
private int key;
private String value;
public HashEntry(int key, String value) {
this.key = key;
this.value = value;
}
}
public static class HashTable {
private HashEntry[] table;
public HashTable() {
this.table = new HashEntry[TABLE_SIZE];
}
public void put(int key, String value) {
int index = hash(key);
while (table[index] != null && table[index].key != key) {
index = (index + 1) % table.length; //线性探测,依次向右查找
}
//可能存在hash冲突, 即hash值一样,但是key不一致
if (table[index] != null) {
//覆盖更新value操作
table[index].value = value;
} else {
//通过线性探测,找一个空的槽位,直接插入
table[index] = new HashEntry(key, value);
}
}
public String get(int key) {
int index = hash