📅  最后修改于: 2023-12-03 14:54:15.641000             🧑  作者: Mango
循环哈希映射是一种可以实现持续增长的键值对集合的数据结构。不同于传统的哈希表只能存储固定大小的键值对,循环哈希映射通过动态的调整内部存储结构,能够存储更多的数据,并且保持高效的查询和更新操作。
在循环哈希映射中,键通过哈希函数转换成一个整数,然后将整数映射到一个哈希表中的位置。哈希表由一个固定大小的数组组成,数组中的每个元素是一个链表,用于解决哈希冲突。当键值对的数量超过哈希表大小时,循环哈希映射会自动进行扩容,重新计算各个键值对的哈希值,并将它们重新映射到新的哈希表中。
循环哈希映射提供以下功能:
循环哈希映射的主要数据结构包括:
/**
* 循环哈希映射的实现
*/
public class MyHashMap {
private static final int INITIAL_CAPACITY = 16; // 初始哈希表大小
private static final double LOAD_FACTOR = 0.75; // 负载因子,用于判断是否需要扩容
private Entry[] table; // 内部哈希表
private int size; // 键值对数量
/**
* 哈希映射的条目
*/
private static class Entry {
private final int key;
private Object value;
private Entry next;
public Entry(int key, Object value) {
this.key = key;
this.value = value;
}
}
/**
* 构造函数,创建循环哈希映射
*/
public MyHashMap() {
table = new Entry[INITIAL_CAPACITY];
size = 0;
}
/**
* 通过键获取对应的值
*
* @param key 键
* @return 值,如果键不存在返回null
*/
public Object get(int key) {
int index = getIndex(key);
Entry entry = table[index];
// 遍历链表查找键值对
while (entry != null) {
if (entry.key == key) {
return entry.value;
}
entry = entry.next;
}
return null; // 键不存在
}
/**
* 插入键值对
*
* @param key 键
* @param value 值
*/
public void put(int key, Object value) {
int index = getIndex(key);
Entry entry = table[index];
// 遍历链表查找键值对
while (entry != null) {
if (entry.key == key) {
entry.value = value; // 更新值
return;
}
entry = entry.next;
}
// 创建新的条目,并插入到链表头部
Entry newEntry = new Entry(key, value);
newEntry.next = table[index];
table[index] = newEntry;
size++;
// 判断是否需要进行扩容
if ((double) size / table.length > LOAD_FACTOR) {
resizeTable();
}
}
/**
* 删除键值对
*
* @param key 键
*/
public void remove(int key) {
int index = getIndex(key);
Entry entry = table[index];
Entry prev = null;
// 遍历链表查找键值对
while (entry != null) {
if (entry.key == key) {
if (prev != null) {
prev.next = entry.next; // 删除当前节点
} else {
table[index] = entry.next; // 删除表头节点
}
size--;
return;
}
prev = entry;
entry = entry.next;
}
}
/**
* 判断键是否存在
*
* @param key 键
* @return 如果键存在返回true,否则返回false
*/
public boolean containsKey(int key) {
int index = getIndex(key);
Entry entry = table[index];
// 遍历链表查找键值对
while (entry != null) {
if (entry.key == key) {
return true;
}
entry = entry.next;
}
return false; // 键不存在
}
/**
* 获取哈希值对应的索引位置
*
* @param key 键
* @return 哈希值对应的索引位置
*/
private int getIndex(int key) {
return Math.abs(key) % table.length;
}
/**
* 扩容操作,重新计算各个键值对的哈希值,并根据新的哈希值重新映射到新的哈希表中
*/
private void resizeTable() {
Entry[] oldTable = table;
table = new Entry[oldTable.length * 2];
size = 0;
// 遍历旧的哈希表,重新映射到新的哈希表中
for (Entry entry : oldTable) {
while (entry != null) {
put(entry.key, entry.value);
entry = entry.next;
}
}
}
}
以上是一个简单的循环哈希映射的Java代码实现。使用该类可以方便地插入、删除、获取和更新键值对,并可以高效地处理大量数据。哈希函数和扩容策略的设计可以根据需求进行调整,以满足特定的场景。