哈希工具类-HashUtil
# 📚 介绍
HashUtil 是 Hutool 核心模块中的哈希算法工具类,提供了丰富的哈希算法实现,涵盖了从经典哈希算法到现代高性能哈希算法的多种实现。该工具类为 Java 开发者提供了便捷的哈希计算解决方案,推荐使用 FNV1 算法。
# 设计理念
- 全面覆盖:涵盖了几乎所有常用的哈希算法
- 简单易用:提供简洁的 API,一行代码即可完成哈希计算
- 高性能:底层实现经过优化,性能优异
- 可扩展性强:采用接口设计,便于扩展新的哈希算法
- 线程安全:所有工具类都是线程安全的,可以在多线程环境下安全使用
# 🔧 核心方法详解
# 1. 经典哈希算法
# additiveHash(String key, int prime)
功能:加法哈希算法
参数:
key:输入字符串prime:一个质数
返回值:hash 结果
示例:
// 使用质数101计算哈希
int hash = HashUtil.additiveHash("Hello Hutool", 101);
Console.log(hash); // 计算结果
# rotatingHash(String key, int prime)
功能:旋转哈希算法
参数:
key:输入字符串prime:质数
返回值:hash 值
示例:
// 使用质数131计算旋转哈希
int hash = HashUtil.rotatingHash("Hello Hutool", 131);
Console.log(hash); // 计算结果
# fnvHash(byte[] data) / fnvHash(String data)
功能:改进的 32 位 FNV 算法 1,推荐使用
参数:
data:输入数据,可以是字节数组或字符串
返回值:hash 结果
示例:
// 计算字符串的FNV哈希
int hash1 = HashUtil.fnvHash("Hello Hutool");
Console.log(hash1); // 计算结果
// 计算字节数组的FNV哈希
byte[] data = "Hello Hutool".getBytes();
int hash2 = HashUtil.fnvHash(data);
Console.log(hash2); // 计算结果
# 2. 常用哈希算法
# bkdrHash(String str)
功能:BKDR 哈希算法
参数:
str:输入字符串
返回值:hash 值
示例:
// 计算BKDR哈希
int hash = HashUtil.bkdrHash("Hello Hutool");
Console.log(hash); // 计算结果
# djbHash(String str)
功能:DJB 哈希算法
参数:
str:输入字符串
返回值:hash 值
示例:
// 计算DJB哈希
int hash = HashUtil.djbHash("Hello Hutool");
Console.log(hash); // 计算结果
# sdbmHash(String str)
功能:SDBM 哈希算法
参数:
str:输入字符串
返回值:hash 值
示例:
// 计算SDBM哈希
int hash = HashUtil.sdbmHash("Hello Hutool");
Console.log(hash); // 计算结果
# 3. 高性能哈希算法
# murmur32(byte[] data)
功能:MurmurHash 算法 32-bit 实现
参数:
data:输入数据
返回值:hash 值
示例:
// 计算MurmurHash32
byte[] data = "Hello Hutool".getBytes();
int hash = HashUtil.murmur32(data);
Console.log(hash); // 计算结果
# murmur64(byte[] data)
功能:MurmurHash 算法 64-bit 实现
参数:
data:输入数据
返回值:hash 值
示例:
// 计算MurmurHash64
byte[] data = "Hello Hutool".getBytes();
long hash = HashUtil.murmur64(data);
Console.log(hash); // 计算结果
# murmur128(byte[] data)
功能:MurmurHash 算法 128-bit 实现
参数:
data:输入数据
返回值:128位 hash 值,封装为 Number128 对象
示例:
// 计算MurmurHash128
byte[] data = "Hello Hutool".getBytes();
Number128 hash = HashUtil.murmur128(data);
Console.log(hash); // 计算结果,格式为:高位,低位
# cityHash64(byte[] data)
功能:CityHash 算法 64-bit 实现
参数:
data:输入数据
返回值:hash 值
示例:
// 计算CityHash64
byte[] data = "Hello Hutool".getBytes();
long hash = HashUtil.cityHash64(data);
Console.log(hash); // 计算结果
# metroHash64(byte[] data, long seed)
功能:MetroHash 算法 64-bit 实现
参数:
data:输入数据seed:种子值
返回值:hash 值
示例:
// 计算MetroHash64
byte[] data = "Hello Hutool".getBytes();
long hash = HashUtil.metroHash64(data, 123456L);
Console.log(hash); // 计算结果
# 🚀 综合示例
# 示例1:多种哈希算法比较
public void hashAlgorithmCompareTest() {
String str = "Hello Hutool";
byte[] data = str.getBytes();
Console.log("字符串:" + str);
Console.log("加法哈希:" + HashUtil.additiveHash(str, 101));
Console.log("旋转哈希:" + HashUtil.rotatingHash(str, 131));
Console.log("FNV哈希:" + HashUtil.fnvHash(str));
Console.log("BKDR哈希:" + HashUtil.bkdrHash(str));
Console.log("DJB哈希:" + HashUtil.djbHash(str));
Console.log("SDBM哈希:" + HashUtil.sdbmHash(str));
Console.log("Murmur32:" + HashUtil.murmur32(data));
Console.log("Murmur64:" + HashUtil.murmur64(data));
Console.log("CityHash64:" + HashUtil.cityHash64(data));
}
# 示例2:使用哈希算法实现简单缓存
public class SimpleCache<K, V> {
private final Map<Integer, V> cache = new HashMap<>();
/**
* 放入缓存
* @param key 键
* @param value 值
*/
public void put(K key, V value) {
// 使用FNV哈希算法计算键的哈希值
int hash = HashUtil.fnvHash(key.toString());
cache.put(hash, value);
}
/**
* 获取缓存
* @param key 键
* @return 值
*/
public V get(K key) {
int hash = HashUtil.fnvHash(key.toString());
return cache.get(hash);
}
/**
* 移除缓存
* @param key 键
*/
public void remove(K key) {
int hash = HashUtil.fnvHash(key.toString());
cache.remove(hash);
}
}
// 使用示例
public void simpleCacheTest() {
SimpleCache<String, String> cache = new SimpleCache<>();
// 放入缓存
cache.put("name", "Hutool");
cache.put("version", "v7");
// 获取缓存
String name = cache.get("name");
String version = cache.get("version");
Console.log("name: " + name); // Hutool
Console.log("version: " + version); // v7
// 移除缓存
cache.remove("name");
String removedName = cache.get("name");
Console.log("removedName: " + removedName); // null
}
# 示例3:哈希算法用于数据分片
public class DataSharding {
private final List<String> nodes;
public DataSharding(List<String> nodes) {
this.nodes = nodes;
}
/**
* 根据key计算应该路由到哪个节点
* @param key 数据key
* @return 节点索引
*/
public int getNodeIndex(String key) {
// 使用MurmurHash32算法计算哈希值
int hash = HashUtil.murmur32(key.getBytes());
// 取模计算节点索引
return Math.abs(hash) % nodes.size();
}
/**
* 根据key获取对应的节点
* @param key 数据key
* @return 节点
*/
public String getNode(String key) {
int index = getNodeIndex(key);
return nodes.get(index);
}
}
// 使用示例
public void dataShardingTest() {
// 模拟分布式节点
List<String> nodes = Arrays.asList(
"node1:8080",
"node2:8080",
"node3:8080",
"node4:8080"
);
DataSharding sharding = new DataSharding(nodes);
// 测试不同key的路由
String[] keys = {"user1", "user2", "user3", "user4", "user5"};
for (String key : keys) {
String node = sharding.getNode(key);
Console.log("Key '" + key + "' 路由到节点: " + node);
}
}
# 🎯 设计优势
- 全面覆盖:涵盖了几乎所有常用的哈希算法,从经典算法到现代高性能算法
- 简单易用:提供简洁的 API,一行代码即可完成哈希计算
- 高性能:底层实现经过优化,性能优异,特别是现代哈希算法如 MurmurHash、CityHash 等
- 线程安全:所有方法都是线程安全的,可以在多线程环境下安全使用
- 多种返回类型:支持 32 位、64 位和 128 位哈希值,满足不同场景需求
- 易于扩展:采用接口设计,便于扩展新的哈希算法
# 📌 注意事项
- 哈希碰撞:任何哈希算法都存在碰撞的可能,对于安全要求高的场景,建议使用加密哈希算法
- 性能考虑:不同哈希算法的性能差异较大,对于性能要求高的场景,建议选择现代高性能哈希算法如 MurmurHash、CityHash 等
- 种子选择:部分哈希算法支持种子参数,不同的种子会产生不同的哈希结果,建议选择合适的种子
- 字符串编码:在计算字符串哈希时,注意字符编码,避免因编码不同导致的哈希结果不同
- 哈希值范围:不同哈希算法的哈希值范围不同,使用时注意处理溢出和负数
# 🚀 总结
HashUtil 是一个功能强大、使用便捷的哈希算法工具类,为 Java 开发者提供了丰富的哈希计算解决方案。它涵盖了从经典哈希算法到现代高性能哈希算法的多种实现,包括 FNV、MurmurHash、CityHash、MetroHash 等。
无论是简单的哈希计算,还是复杂的分布式数据分片和缓存实现,HashUtil 都能轻松应对。通过合理选择哈希算法,可以提高系统的性能和可靠性。
HashUtil 是 Hutool 编码解码模块中的重要组成部分,与其他编码工具类一起,构成了完整的编码解码解决方案,为 Java 开发者提供了丰富的编码解码工具。