【问题标题】:Implementing Good hashCode function in java?在java中实现好的hashCode函数?
【发布时间】:2013-10-13 02:51:14
【问题描述】:

我现在知道一些内置实用程序,例如来自 Apache commons lang 的 HashCodeBuilder,但我试图了解如何自己实现它,并在http://en.wikipedia.org/wiki/Java_hashCode()遇到了 Employee 类的 hascode 函数示例

在谷歌的任何地方,都建议使用相同的技术,例如将非零值与奇质数相乘,然后将其相加 使用实例变量(对实例变量执行此操作)。

问题:-

1) 为什么我们不能将employeeId 作为hascode 返回,因为它会是唯一的。它简单并且服务于hascode目的。 同意,如果它不是唯一的,我们可能需要这种技术。对吗?

2)即使员工ID不是唯一的,为什么建议乘以奇数素数?为什么取任何该死的整数不是 算好的吗?

更新:-

Peter 我运行了你提到的打印示例

[0, 32, 64, 96, 128, 160, 192, 224, 288, 256, 352, 320, 384]

[0, 32, 64, 96, 128, 160, 192, 224, 288, 256, 352, 320, 384]

我假设现在的输出与预期的一样理解这个概念 正如您在回答中提到的那样

[373, 343, 305, 275, 239, 205, 171, 137, 102, 68, 34, 0]

[0, 34, 68, 102, 137, 171, 205, 239, 275, 305, 343, 373]

正如您在评论中所建议的那样,此示例表明即使是唯一的哈希码也可以最终出现在同一个存储桶中。这怎么 示例证明了这种行为?您的意思是整数 373 和整数 0 最终在同一个桶中吗?

素数在本例中有何帮助,而 34 又有何帮助?

【问题讨论】:

    标签: java hashcode hash-collision hash-code-uniqueness


    【解决方案1】:

    为什么我们不能将employeeId 作为hascode 返回,因为它会是独一无二的。它简单并且服务于hascode目的。同意,如果它不是唯一的,我们可能需要这种技术。对吗?

    它的独特性并不重要。乘以一个素数是将多个字段合并为一个 hashCode 的好方法,但听起来你只有一个,所以不会有太大区别。

    即使员工 id 不是唯一的,为什么建议乘以奇数素数?为什么取任何该死的整数都不好?

    如果乘以偶数,hashCode 的最低位是多少?它有多随机/有用?


    注意:Integer 的每个 hashCode() 都是唯一的,但要获得正确的整数值组合,当它们减少到 HashMap 的容量时,它们实际上映射到同一个桶。在此示例中,条目按添加时的相反顺序显示,因为每个条目都映射到同一个存储桶。

    HashSet<Integer> integers = new HashSet<>();
    for (int i = 0; i <= 400; i++)
        if ((hash(i) & 0x1f) == 0)
            integers.add(i);
    HashSet<Integer> integers2 = new HashSet<>();
    for (int i = 400; i >= 0; i--)
        if ((hash(i) & 0x1f) == 0)
            integers2.add(i);
    System.out.println(integers);
    System.out.println(integers2);
    
    
    static int hash(int h) {
        // This function ensures that hashCodes that differ only by
        // constant multiples at each bit position have a bounded
        // number of collisions (approximately 8 at default load factor).
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }
    

    打印

    [373, 343, 305, 275, 239, 205, 171, 137, 102, 68, 34, 0]
    [0, 34, 68, 102, 137, 171, 205, 239, 275, 305, 343, 373]
    

    【讨论】:

    • "如果乘以偶数,hashCode 的最低位是多少?"它有多随机/有用?你能详细说明一下吗。在此先感谢:)
    • 即使我们有多个字段,为什么乘以素数是将多个字段合并为一个 hashCode 的好方法?为什么不只是empId?我认为答案在于它的独特性并不重要。没看懂是什么意思?根据理解,唯一性很重要,以便将其存储在单独的存储桶中,用于基于哈希的数据结构的不相等对象?
    • 如果你乘以一个偶数,你会得到一个偶数,所以最低位总是 0 并且没有任何值。
    • 你想要一个随机的 hashCode,而素数最不可能得到某种模式,这意味着并非所有值都相等。您使用 9 的图像,并且您使用大小为 3 的倍数的 Hashtable。这将导致每 3 个存储桶中有 2 个未被使用,或者更糟糕的是可能只有 9 个存储桶中的一个被使用。主要因素越小,您就越有可能遇到一些表现不佳的情况
    • 将一个值乘以一个素数,这不会使其变得更加随机。
    猜你喜欢
    • 1970-01-01
    • 2010-10-19
    • 2019-06-02
    • 2020-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-30
    • 1970-01-01
    相关资源
    最近更新 更多