我有一个java应用程序,我想在其中生成字符串的
long
id(以便将这些字符串存储在neo4j中)。为了避免数据重复,我想为存储在 long
整数中的每个字符串生成一个 id,该 id 对于每个字符串应该是唯一的。我怎样才能做到这一点?
这段代码将计算出相当好的哈希值:
String s = "some string";
long hash = UUID.nameUUIDFromBytes(s.getBytes()).getMostSignificantBits();
为什么不看看 String 的
hashcode()
函数,而直接采用它来使用 long 值呢?
顺便说一句。如果有办法为每个字符串创建唯一的 ID,那么您就会找到一种压缩算法,能够将每个字符串打包为 8 个字节(根据定义不可能)。
long
有 64 位。长度为 9 的 String
有 72 位。来自鸽子洞原理 - 你无法获得 9 个字符长字符串到 long
的唯一哈希值。
如果您仍然想要
long
哈希:您可以为 String->int
、hash1()
和 hash2()
采用两个标准[不同!] 哈希函数并计算: hash(s) = 2^32* hash1(s) + hash2(s)
将 CRC32 与 Adler32 结合起来可以实现简单的 64 位哈希。当然,这种组合不如现代哈希技术那么强大,但对于本机提供 CRC 库的语言来说,它是“可移植的”。 Java
中的示例:
package com.example;
import java.util.zip.Adler32;
import java.util.zip.CRC32;
public class MySimpleHash {
/**
* Calculate a 64 bits hash by combining CRC32 with Adler32.
*
* @param bytes a byte array
* @return a hash number
*/
public static long getHash(byte[] bytes) {
CRC32 crc32 = new CRC32();
Adler32 adl32 = new Adler32();
crc32.update(bytes);
adl32.update(bytes);
long crc = crc32.getValue();
long adl = adl32.getValue();
return (crc << 32) | adl;
}
public static void main(String[] args) {
String string = "This is a test string";
long hash = getHash(string.getBytes());
System.out.println("output: " + hash);
}
}
output: 7732385261082445741
Python中的示例:
#!/usr/bin/python3
import zlib
def get_hash(bytes):
return zlib.crc32(bytes) << 32 | zlib.adler32(bytes)
string = "This is a test string"
hash = get_hash(string.encode())
print("output:", hash)
output: 7732385261082445741
这个要点比较了一些哈希方法:https://gist.github.com/fabiolimace/507eac3d35900050eeb9772e5b1871ba
http://stackoverflow.com/questions/415953/generate-md5-hash-in-java
编辑:删除,我错过了long
http://en.wikipedia.org/wiki/Perfect_hash_function
字符串,因此您可以拥有完美的映射。但请注意,该映射也可能成为主要瓶颈。
使用 64 位(长)哈希,如果哈希不超过 100 亿个字符串,则可以实现零冲突。 一个很棒的 64 位哈希函数是 mzHash64():