如何在 Java 中将长字符串“哈希”为 String[64]

问题描述 投票:0回答:3

我有一个可与 MySQL 数据库配合使用的 Java 应用程序。

我希望能够存储长文本并检查表是否包含它们。为此,我想使用索引,并通过减少全文的“哈希”进行搜索。

MY_TABLE [
    full_text: TEXT
    text_hash: varchar(255) - indexed
]

问题是,我不能将 String.hashCode() 用作:

  1. 不同 JVM 版本的实现可能会有所不同。
  2. 值太短,意味着很多碰撞。

我想找到一个快速哈希函数,它将读取长文本值并为其生成一个长哈希值,例如 64 个符号长。

java mysql hash
3个回答
4
投票

这种可靠的哈希方法并不快。不过,它们可能足够快。您正在寻找一种加密消息摘要方法(例如用于识别 P2P 网络中的文件或 Git 中的提交的方法)。查找 MessageDigest 类,然后选择您的算法(SHA1、MD5、SHA256 等)。

这样的哈希函数将采用字节作为参数,并生成字节作为结果,因此请确保使用常量编码(例如 UTF8)转换字符串,并转换生成的字节数组(通常为 16 或 20 字节) ) 到使用十六进制或 Base64 编码的可读字符串。


1
投票

我建议您重新访问

String.hashCode()

首先,它不会因实现而异。指定了确切的哈希值;请参阅 String.hashCode javadoc 规范。

其次,虽然字符串哈希算法并不是最好的(而且它肯定会比加密哈希有更多的冲突),但它确实在将哈希值分布在 32 位结果空间上方面做得相当好。例如,我快速检查了我机器上的一个文本文件 (

/usr/share/dict/web2a
),其中包含 235,880 个单词,并且存在 6 冲突。

第三和第四:

String.hashCode()
应该比加密哈希要快得多,并且哈希值所需的存储应该要小得多。

如果您将字符串存储在数据库表中,并且它们的哈希值已建立索引,那么出现一些冲突应该不重要。查找字符串应该很快就能找到正确的数据库行,而且与数据库 I/O 相比,(也许)检查几个实际字符串应该非常快。


0
投票

我建议使用 mzHash64,一个非常简单、快速的函数,其碰撞次数非常接近理想的通用哈希函数

public static long mzHash64(byte[] data, int start, int length, long seed) {    
    long hash = 0xD45E69F901E72147L ^ seed;

    for(int i = 0; i < length; i++)
        hash = 0x3631754B22FF2D5CL * (i + data[start + i]) ^ (hash << 2) ^ (hash >>> 2);

    return hash;
}

public static long mzHash64(String str) {
    byte[] data = str.getBytes();
    return mzHash64(data, 0, data.length, 0);
}

来源:https://github.com/matteo65/mzHash64

32位版本:https://github.com/matteo65/mzHash32

© www.soinside.com 2019 - 2024. All rights reserved.