将字符串哈希到几个(100-200)无符号整数

时间:2012-10-28 08:16:18

标签: java

我正在尝试实现this website上定义的逻辑。其中一个步骤是:

  
      
  • 将每个服务器字符串哈希到几个(100-200)无符号整数
  •   

但我对此感到困惑。有人可以告诉我这意味着什么,以便我可以手动实现逻辑?

// This count is always 2 as per my current setup
int availableservers = Client.getAvailableServers().size();  

String key = "MyKey";
int keyid = key.hashCode();
int v = keyid % 1;
String valess = (String) mcc.get(key,v);

3 个答案:

答案 0 :(得分:3)

您引用的文章包含指向其SVN代码库的链接:

svn://svn.audioscrobbler.net/misc/ketama/

在这里,它们似乎包含了Java实现:

svn://svn.audioscrobbler.net/misc/ketama/java_ketama/SockIOPool.java

在代码中,您将找到以下内容:

for(long j = 0; j < factor; j++) {
  byte[] d = md5.digest((servers[i]+"-"+j).getBytes());
  for(int h=0;h<4;h++) {
    Long k = 
        ((long)(d[3+h*4]&0xFF) << 24)
      | ((long)(d[2+h*4]&0xFF) << 16)
      | ((long)(d[1+h*4]&0xFF) << 8)
      | ((long)(d[0+h*4]&0xFF));
    buckets.put(k, servers[i]);
    log.debug( "++++ added " + servers[i] + " to server bucket" );
  }             
}

此代码为每个服务器创建了总共factor个哈希值。请注意for循环在散列之前将当前值j附加到字符串server[i]

将此与Frank Pavageau的答案相结合,你很快就会明白发生了什么。

答案 1 :(得分:2)

我猜ketama hash是使用MD5计算的。我找到了示例实现here

public static Long md5HashingAlg(String key) {
  MessageDigest md5 = null;
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException( "md5 algorythm found");            
        }
    }
    md5.reset();
    md5.update(key.getBytes());
    byte[] bKey = md5.digest();
    long res = ((long)(bKey[3]&0xFF) << 24) | ((long)(bKey[2]&0xFF) << 16) | ((long)(bKey[1]&0xFF) << 8) | (long)(bKey[0]&0xFF);
    return res;
}

答案 2 :(得分:1)

Duncan是对的,只需查看来源,看看这个特定的实现是如何运作的。

然而,从概念上讲,无论使用何种哈希算法,如果你需要基于相同键的多个哈希值,你需要做的就是将键连接到几个“常量”,或者至少是已知和可重复的值:

String key = "MyKey";
List<Integer> hashes = new ArrayList<>();
for (String s : Arrays.asList("", "extra1", "extra2")) {
    hashes.add((key + s).hashCode());
}

这相当于围绕整数“连续体”分布散列,以重用文章的术语。所以你也可以这样做,就像你实现hashCode()一样:

String key "MyKey";
List<Integer> hashes = new ArrayList<>();
int hash = key.hashCode();
for (int i = 0; i < 100; i++) {
    hashes.add(hash);
    hash = 31 * hash + 1234567;
}