【问题标题】:Testing / Profiling a hashcode function for java hashmap测试/分析java hashmap的hashcode函数
【发布时间】:2011-04-23 07:05:01
【问题描述】:

如何测试/分析 Java 中的 hashCode() 实现?即它是否合理均匀地分配我的测试数据等? java API本身有没有简单粗暴的方法?

【问题讨论】:

    标签: java collections hashmap


    【解决方案1】:
    Map<Integer, Integer> hashCodes = new HashMap<Integer, Integer>();
    for (YourHashcodedClass testData: largeCollectionOfTestData) {
        Integer hashCode = Integer.valueOf(testData.hashCode());
        Integer occurrences = hashCodes.get(hashCode);
        if (occurrences == null) {
            occurrences = 0;
        }
        hashCodes.put(hashCode, occurrences+1);
    }
    

    然后分析您的地图是否有碰撞。

    【讨论】:

    • 地图包含您的哈希码。任何出现次数 > 1 的条目都是冲突。
    【解决方案2】:

    老实说,如果您遵循最佳做法,则不必分析或测试您的 hashCode() 方法的分布。请参阅下面来自Effective Java 的哈希码配方。此外,即使您写得不好,HashMap 实现也会重新散列您的结果以减少冲突:

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

    您也可以使用Apache Commons Lang 中的HashCodeBuilder 为您构建哈希码。

    Effective Java 2nd Edition hash code recipe

    • 在名为resultint 变量中存储一些恒定的非零值,例如17。
    • 为每个字段计算int 哈希码c
      • 如果字段是boolean,则计算(f ? 1 : 0)
      • 如果字段是byte, char, short, int,则计算(int) f
      • 如果字段是long,则计算(int) (f ^ (f &gt;&gt;&gt; 32))
      • 如果字段是float,则计算Float.floatToIntBits(f)
      • 如果字段是double,计算Double.doubleToLongBits(f),然后像上面一样散列结果long
      • 如果该字段是对象引用,并且此类的equals 方法通过递归调用equals 来比较该字段,则在该字段上递归调用hashCode。如果该字段的值为null,则返回0。
      • 如果该字段是一个数组,则将其视为每个元素都是一个单独的字段。如果数组字段中的每个元素都很重要,您可以使用 1.5 版中添加的 Arrays.hashCode 方法之一。
    • 将哈希码c组合成result如下:result = 31 * result + c;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-08
      • 1970-01-01
      • 2019-12-02
      相关资源
      最近更新 更多