好的哈希函数弦乐好的哈希函数弦乐(Good Hash Function for Strings)

2019-05-10 09:14发布

我试图想出一个串好的哈希函数。 我想这可能是总结Unicode值的字符串中的前五个字符是一个好主意(假设它有五个,否则停止在那里结束)。 那会是一个好主意,还是坏事呢?

我在Java中这样做,但我无法想象这将使多大的差别。

Answer 1:

通常哈希不会做算术,否则stoppots将具有相同的哈希值。

你不会限制它的前n个字符,否则房子和房子将具有相同的哈希值。

一般来说hashs取值和一个素数相乘(使得它更容易产生独特的哈希值),所以,你可以这样做:

int hash = 7;
for (int i = 0; i < strlen; i++) {
    hash = hash*31 + charAt(i);
}


Answer 2:

如果它是一个安全的事情,你可以使用Java加密:

import java.security.MessageDigest;

MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(stringToEncrypt.getBytes());
String encryptedString = new String(messageDigest.digest());


Answer 3:

你或许应该使用String.hashCode() 。

如果你真的想实现自己的hashCode:

不要试图从哈希码的计算中排除的对象的显著部分来提高性能 - 约书亚布洛赫有效的Java

只使用前五个字符是一个坏主意 。 想想层次名称,如URL:他们都将有相同的散列码(因为他们都开始以“http://”,这意味着它们被存储在一个哈希表一样斗下,表现出可怕的性能。

以下是转述从“字符串的hashCode战争故事有效的Java ”:

在之前1.2至多16个字符所检查的所有版本中实现的字符串的散列函数,均匀分布在整个串间隔,开始与第一个字符。 对于大的集合层次名称的,如URL,这个哈希函数显示可怕的行为。



Answer 4:

如果你是在Java中这样做那么你为什么这样做呢? 只需拨打.hashCode()的字符串



Answer 5:

番石榴的HashFunction ( Javadoc中 )提供体面的非加密散列强。



Answer 6:

由尼克·本功能是好的,但如果你使用新的字符串(字节[]字节)进行改造字符串,它失败了。 您可以使用此功能来做到这一点。

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());
}

可能这可以帮助别人



Answer 7:

// 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;
}

源 后面djb2散列函数逻辑- SO



Answer 8:

FNV-1被传言是字符串好的哈希函数。

对于长字符串(长于,比方说,约200字),你可以得到很好的表现出来的的MD4散列函数。 作为一种加密功能,它是大约15年前被打破,但对于非加密的目的,还是很不错的,而且出奇的快。 在Java的情况下,你将不得不在16位转换char值转换为32位字,例如,通过这样的值分组到对。 Java中的快速实现MD4的可以发现sphlib 。 可能是矫枉过正的教室转让的情况下,但在其他方面值得一试。



Answer 9:

如果你想看到的行业标准的实施,我想看看java.security.MessageDigest中 。

“消息摘要是采用任意大小的数据,并输出一个固定长度的散列值安全单向散列函数。”



Answer 10:

SDBM:这个算法是为SDBM创建(NDBM的公共领域重新实现)数据库库

static unsigned long sdbm(unsigned char *str)
{   
    unsigned long hash = 0;
    int c;
    while (c = *str++)
            hash = c + (hash << 6) + (hash << 16) - hash;

    return hash;
}


Answer 11:

这里有一个链接 ,说明许多不同的散列函数,现在我希望为自己的特定问题的ELF散列函数。 它输入任意长度的字符串。



Answer 12:

         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();
}


Answer 13:

这将避免任何碰撞,这将是快速的,直到我们使用的计算换挡。

 int k = key.length();
    int sum = 0;
    for(int i = 0 ; i < k-1 ; i++){
        sum += key.charAt(i)<<(5*i);
    }


Answer 14:

它是一个好主意,试图开发串一个良好的事呢功能时与奇数工作。 此功能需要一个字符串,并返回一个索引值,到目前为止,它的工作相当不错。 而且具有更少的碰撞。 该指数范围从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解析,因为它增加之类的词“熊”(0 * B)+(1 * E)+(2 * A)+(3 * R),这将给你一个int值一起玩。 上述第一哈希函数的碰撞“这里”和“听”,但仍有很大的给一些好的唯一值。 在下面的一个不是以“在这里”发生碰撞,“听”,因为我乘每个字符与索引,因为它增加。

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;
}


Answer 15:

下面是我使用的哈希表我建立了一个简单的哈希函数。 它基本上是把文本文件,并存储每个字在表示字母顺序排列的索引。

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

让下面的文字输入:阿提库斯到杰姆说有一天,“我宁愿你出手在后院锡罐,但我知道鸟后你会去。 拍摄所有你想要的蓝鸟,如果你可以打他们,但是请记住这是一种罪过杀死一只知更鸟。”这是我听到过的唯一一次阿提库斯说这是一种罪过做一些事情,我问Maudie小姐约它。 “你父亲是对的,”她说。 “Mockingbirds不做一两件事,除了化妆音乐让我们享受。 他们不要吃了人们的花园,不要窝在玉米婴儿床,他们没有做一两件事,但唱他们的心我们。 这就是为什么它是一种罪过杀死一只知更鸟。

这将是输出:

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


文章来源: Good Hash Function for Strings