从多个 Java 字符串对象创建哈希
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10587506/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Creating a hash from several Java string objects
提问by PNS
What would be the fastest and more robust (in terms of uniqueness) way for implementing a method like
实现类似方法的最快和更健壮(就唯一性而言)的方式是什么?
public abstract String hash(String[] values);
The values[]
array has 100 to 1,000 members, each of a which with few dozen characters, and the method needs to be run about 10,000 times/sec on a different values[]
array each time.
该values[]
数组有 100 到 1,000 个成员,每个成员有几十个字符,并且该方法每次需要在不同的values[]
数组上运行大约 10,000 次/秒。
Should a long string be build using a StringBuilder
buffer and then a hash method invoked on the buffer contents, or is it better to keep invoking the hash method for each string from values[]
?
应该使用StringBuilder
缓冲区构建一个长字符串,然后在缓冲区内容上调用散列方法,还是最好继续为每个字符串调用散列方法values[]
?
Obviously a hash of at least 64 bits is needed (e.g., MD5) to avoid collisions, but is there anything simpler and faster that could be done, at the same quality?
显然,需要至少 64 位的散列(例如,MD5)来避免冲突,但是在相同的质量下,是否可以更简单、更快地完成?
For example, what about
例如,关于
public String hash(String[] values)
{
long result = 0;
for (String v:values)
{
result += v.hashCode();
}
return String.valueOf(result);
}
回答by Marko Topolnik
Definitely don't use plain addition due to its linearity properties, but you can modify your code just slightly to achieve very good dispersion.
由于其线性特性,绝对不要使用普通加法,但您可以稍微修改代码以实现非常好的分散。
public String hash(String[] values) {
long result = 17;
for (String v:values) result = 37*result + v.hashCode();
return String.valueOf(result);
}
回答by Oliver Coleman
It doesn't provide a 64 bit hash, but given the title of the question it's probably worth mentioning that since Java 1.7 there is java.util.Objects#hash(Object...).
它不提供 64 位哈希,但鉴于问题的标题,可能值得一提的是,自 Java 1.7 以来,就有java.util.Objects#hash(Object...)。
回答by girivasan4
Here is the simple implementation using Objects class available from Java 7.
这是使用 Java 7 提供的 Objects 类的简单实现。
@Override
public int hashCode()
{
return Objects.hash(this.variable1, this.variable2);
}
回答by Mark Jeronimus
You should watch out for creating weaknesses when combining methods. (The java hash function and your own). I did a little research on cascaded ciphers, and this is an example of it. (the addition might interfere with the internals of hashCode().
在组合方法时,您应该注意创建弱点。(java 哈希函数和你自己的)。我对级联密码做了一些研究,这是一个例子。(添加可能会干扰 hashCode() 的内部结构。
The internals of hashCode() look like this:
hashCode() 的内部结构如下所示:
for (int i = 0; i < len; i++) {
h = 31*h + val[off++];
}
so adding numbers together will cause the last characters of all strings in the array to just be added, which doesn't lower the randomness (this is already bad enough for a hash function).
所以将数字加在一起会导致数组中所有字符串的最后一个字符被添加,这不会降低随机性(这对于散列函数来说已经足够糟糕了)。
If you want real pseudorandomness, take a look at the FNVhash algorithm. It is the fastest hash algorithm out there that is especially designed for use in HashMaps.
如果您想要真正的伪随机性,请查看FNV哈希算法。它是目前最快的哈希算法,专为在 HashMap 中使用而设计。
It goes like this:
它是这样的:
long hash = 0xCBF29CE484222325L;
for(String s : strings)
{
hash ^= s.hashCode();
hash *= 0x100000001B3L;
}
^ This is not the actual implementation of FNV as it takes ints as input instead of bytes, but I think it works just as well.
^ 这不是 FNV 的实际实现,因为它接受整数而不是字节作为输入,但我认为它也能正常工作。
回答by AlexR
First, hash code is typically numeric, e.g. int
. Moreover your version of hash function create int and then makes its string representation that IMHO does not have any sense.
首先,哈希码通常是数字,例如int
。此外,您的哈希函数版本创建 int 然后使其字符串表示,恕我直言没有任何意义。
I'd improve your hash method as following:
我会改进你的哈希方法如下:
public int hash(String[] values) {
long result = 0;
for (String v:values) {
result = result * 31 + v.hashCode();
}
return result;
}
Take a look on hashCode()
implemented in class java.lang.String
看看hashCode()
在课堂上实现java.lang.String