我试图为字符串想出一个很好的哈希函数。我当时想对字符串中的前五个字符的unicode值进行汇总(假设它有五个,否则就在结尾处停止)是一个好主意。这是一个好主意,还是一个坏主意?
我正在用Java进行此操作,但是我无法想象这会带来很大的不同。
String
自己的hashCode()
?
我试图为字符串想出一个很好的哈希函数。我当时想对字符串中的前五个字符的unicode值进行汇总(假设它有五个,否则就在结尾处停止)是一个好主意。这是一个好主意,还是一个坏主意?
我正在用Java进行此操作,但是我无法想象这会带来很大的不同。
String
自己的hashCode()
?
Answers:
通常哈希不会做算术,否则stop
和pots
将具有相同的哈希值。
并且您不会将其限制为前n个字符,因为否则house和house将具有相同的哈希值。
通常,哈希采用值并将其乘以质数(使其更有可能生成唯一的哈希),因此您可以执行以下操作:
int hash = 7;
for (int i = 0; i < strlen; i++) {
hash = hash*31 + charAt(i);
}
如果这是安全的事情,则可以使用Java crypto:
import java.security.MessageDigest;
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(stringToEncrypt.getBytes());
String encryptedString = new String(messageDigest.digest());
您可能应该使用String.hashCode()。
如果您真的想自己实现hashCode:
不要试图从哈希码计算中排除对象的重要部分以提高性能-高效Java的Joshua Bloch
只使用前五个字符是个坏主意。考虑一下URL之类的层次结构名称:它们都具有相同的哈希码(因为它们都以“ http://”开头,这意味着它们存储在哈希图中的同一存储桶下,表现出糟糕的性能。
这是一个有关“ 有效Java ”中的String hashCode的战争故事:
在1.2之前的所有发行版中实现的String哈希函数最多检查16个字符,从第一个字符开始,在整个字符串中均匀分布。对于大量的层次结构名称(例如URL),此哈希函数显示了可怕的行为。
如果您使用Java进行此操作,那么为什么要这样做呢?只需调用.hashCode()
字符串
.hashCode()
。而是使用一些已知的算法。
String::hashCode
是在JDK中指定的,因此它与类的存在一样可移植java.lang.String
。
Nick提供的此功能很好,但是如果使用新的String(byte [] bytes)进行到String的转换,它将失败。您可以使用此功能执行此操作。
private static final char[] hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
public static String byteArray2Hex(byte[] bytes) {
StringBuffer sb = new StringBuffer(bytes.length * 2);
for(final byte b : bytes) {
sb.append(hex[(b & 0xF0) >> 4]);
sb.append(hex[b & 0x0F]);
}
return sb.toString();
}
public static String getStringFromSHA256(String stringToEncrypt) throws NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(stringToEncrypt.getBytes());
return byteArray2Hex(messageDigest.digest());
}
也许这可以帮助某人
// djb2 hash function
unsigned long hash(unsigned char *str)
{
unsigned long hash = 5381;
int c;
while (c = *str++)
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return hash;
}
如果您想查看行业标准实现,请查看java.security.MessageDigest。
“消息摘要是安全的单向哈希函数,可接收任意大小的数据并输出固定长度的哈希值。”
public String hashString(String s) throws NoSuchAlgorithmException {
byte[] hash = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
hash = md.digest(s.getBytes());
} catch (NoSuchAlgorithmException e) { e.printStackTrace(); }
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hash.length; ++i) {
String hex = Integer.toHexString(hash[i]);
if (hex.length() == 1) {
sb.append(0);
sb.append(hex.charAt(hex.length() - 1));
} else {
sb.append(hex.substring(hex.length() - 2));
}
}
return sb.toString();
}
在尝试为字符串开发良好的hast函数时,最好使用奇数。这个函数接受一个字符串并返回一个索引值,到目前为止,它的工作还不错。并且碰撞更少 索引范围从0-300甚至可能更多,但是到目前为止,即使是像“机电工程”这样的长字,我也没有得到更高的体现
int keyHash(string key)
{
unsigned int k = (int)key.length();
unsigned int u = 0,n = 0;
for (Uint i=0; i<k; i++)
{
n = (int)key[i];
u += 7*n%31;
}
return u%139;
}
您可以做的另一件事是,将每个字符int解析结果乘以索引,例如“ bear”(0 * b)+(1 * e)+(2 * a)+(3 * r)一词,这将为您提供索引要使用的int值。上面的第一个哈希函数在“ here”和“ hear”处发生碰撞,但是在提供一些良好的唯一值方面仍然很棒。下面的一个不会与“ here”和“ hear”发生冲突,因为随着字符的增加,我会将每个字符与索引相乘。
int keyHash(string key)
{
unsigned int k = (int)key.length();
unsigned int u = 0,n = 0;
for (Uint i=0; i<k; i++)
{
n = (int)key[i];
u += i*n%31;
}
return u%139;
}
这是我用于构建的哈希表的简单哈希函数。它基本上用于获取文本文件,并将每个单词存储在代表字母顺序的索引中。
int generatehashkey(const char *name)
{
int x = tolower(name[0])- 97;
if (x < 0 || x > 25)
x = 26;
return x;
}
这基本上是根据单词的第一个字母对单词进行哈希处理。因此,以'a'开头的单词的哈希键为0,'b'的值为1,依此类推,'z'的值为25。数字和符号的哈希键为26。这是一个优点; 您可以轻松,快速地计算出给定单词在哈希表中的索引位置,因为所有单词都按字母顺序排列,如下所示:代码可以在这里找到:https://github.com/abhijitcpatil/general
提供以下文本作为输入:阿提克斯有一天对杰姆说: “我希望您在后院的锡罐上开枪,但我知道您会追赶鸟类。射杀所有想要的蓝鸟,如果可以击中它们,但要记住杀死一只知更鸟是一种罪过。” 那是我唯一一次听到Atticus说做某事是一种罪过,我问Maudie小姐。她说:“你父亲的权利。” “模仿鸟除了做音乐让我们欣赏之外,没有做任何事情。他们不吃人的花园,不筑巢于玉米婴儿床,他们不做任何事情,而是为我们献出自己的心。这就是为什么杀死一只模仿鸟是一种罪过。
这将是输出:
0 --> a a about asked and a Atticus a a all after at Atticus
1 --> but but blue birds. but backyard
2 --> cribs corn can cans
3 --> do don’t don’t don’t do don’t do day
4 --> eat enjoy. except ever
5 --> for for father’s
6 --> gardens go
7 --> hearts heard hit
8 --> it’s in it. I it I it’s if I in
9 --> jays Jem
10 --> kill kill know
11 -->
12 --> mockingbird. music make Maudie Miss mockingbird.”
13 --> nest
14 --> out one one only one
15 --> people’s
16 --> 17 --> right remember rather
18 --> sin sing said. she something sin say sin Shoot shot said
19 --> to That’s their thing they They to thing to time the That to the the tin to
20 --> us. up us
21 -->
22 --> why was was want
23 -->
24 --> you you you’ll you
25 -->
26 --> “Mockingbirds ” “Your ‘em “I’d
这样可以避免任何冲突,而且在我们在计算中使用移位之前将非常快。
int k = key.length();
int sum = 0;
for(int i = 0 ; i < k-1 ; i++){
sum += key.charAt(i)<<(5*i);
}