【问题标题】:Non cryptographic hashing in Java using unsigned integersJava中使用无符号整数的非加密哈希
【发布时间】:2017-08-22 04:21:02
【问题描述】:

我正在寻找一个可以在 Java 中用于非加密目的的散列函数。挑战在于大多数散列函数返回的有符号整数值 (-,0,+) 不能在每个上下文中用作标识符(例如,负整数不能在 URL 中使用)。这个问题的一个解决方案是我想出的是使用 32 位有符号整数并将其转换为 32 位无符号整数并将其存储在一个长整数中。这工作得很好。然而,32 位随机信息使得哈希冲突在我们的设置中过于频繁。解决此问题的一种方法是使用 64 位散列函数(相同的 SipHash 工作正常)并通过向右移动 1 并将 MSB 位置为 0 来将该有符号整数转换为无符号整数。我试图用 Java >> 运算符来实现这一点,但结果没有意义。

//Using Guava
private final static HashFunction hashFunction = Hashing.sipHash24();

    private static int getRandomInt() {
        return hashFunction.newHasher().putLong(rnd.nextLong()).hash().asInt();
    }

    private static long getRandomLong(){
        return hashFunction.newHasher().putLong(rnd.nextLong()).hash().asLong();
    }

位移:

 System.out.println(Long.toBinaryString(-2147483648L >> 1));
 1111111111111111111111111111111111000000000000000000000000000000

我遗漏了什么,如何在 Java 中将 62 位无符号整数哈希值存储在 64 位 int(long)中?

更新1:

经过一番研究,我终于找到了一种正确显示 >>> 对 Long 值的影响的方法:

        System.out.println(
          String.format("%64s", Long.toBinaryString(-2147483648L))
            .replace(' ', '0'));
        System.out.println(
          String.format("%64s", Long.toBinaryString(-2147483648L >>> 1))
            .replace(' ', '0'));

        1111111111111111111111111111111110000000000000000000000000000000
        0111111111111111111111111111111111000000000000000000000000000000

【问题讨论】:

  • 为什么不能在 url 中使用负值?另外,尝试>>>(无符号右移)而不是>>(有符号右移)。
  • @ElliottFrisch 谢谢!因为 /-123123/ 看起来与 /123123/ 非常相似,并且基于此值的路由不支持它为负数。

标签: java hash


【解决方案1】:

a >> b

将 a 向右移动 b 位。在左侧,它重复了已经存在的位(符号扩展!)。 例子:

  • 101010 >> 1 = 110101
  • 010101 >> 1 = 001010

a >>> b

也将 a 向右移动 b 位,但不进行符号扩展。它总是在左边加零:

  • 101010 >>> 1 = 010101
  • 010101 >>> 1 = 001010

【讨论】:

    猜你喜欢
    • 2021-01-23
    • 2017-09-19
    • 2016-04-21
    • 2013-05-05
    • 2018-07-12
    • 2020-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多