【问题标题】:Uniform distribution of hashcode()hashcode() 的均匀分布
【发布时间】:2016-08-07 03:45:20
【问题描述】:

我将我的班级定义为:

final class Key<T extends Comparable<T>> {
    private final T q;
    private final T o;
    public Key(T q1, T o1) {
        q = q1;
        o = o1;
    }

    @Override
    public boolean equals(Object obj) {
        if(obj != null && obj instanceof Key) {
            Key<T> s = (Key<T>)obj;
            return q.equals(s.q) && o.equals(s.o);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return Objects.hash(q,o);
    }
}

我还定义了一个数组来包含对象 key 。例如:

Object arr[] = new Object[100];
Key<String> k = new Key<>("a","b");
int h = k.hashcode();
...
arr[h+i % h] = k; //i from 1 to 10 for example

问题是 hashcode() 可以返回负值所以

arr[h+i % h] = k;

可以在数组索引之外返回错误。这就是为什么我将代码更改为(基于我对避免 hashcode() 返回负值的搜索):

@Override
        public int hashCode() {
            return (Objects.hash(q,o)&0x7FFFFFFF);
        }

如果我这样做,hashcode() 的均匀分布是否会改变?我的意思是两个不同对象具有相同值的概率会增加还是不增加?

【问题讨论】:

  • 如何将键对象创建为 Key。它应该给编译器错误,因为类型 Key 的参数数量不正确
  • 是的,我的错误。我也编辑了它。谢谢
  • 你可以看看 murmur hash 有很好的分布。也不能是负值

标签: java hashcode hash-collision


【解决方案1】:

请关注MurmurhashMurmurHash - what is it? 幸运的是,Google guava 已经为此做好了实现。

Guava 方式如下例所示 我们有以下课程

import com.google.common.hash.HashCode; import com.google.common.hash.HashFunction; import com.google.common.hash.Hashing;

使用上面的类我有我的方法来生成下面的哈希码

/**
     * getMurmur128Hash.
     * 
     * @param content
     * @return HashCode
     */
    public static HashCode getMurmur128Hash(String content) {
        final HashFunction hf = Hashing.murmur3_128();
        final HashCode hc = hf.newHasher().putString(content, Charsets.UTF_8).hash();
        return hc;
    }
    /**
     * getAbsMurmur128HashAsLongVal.
     * 
     * @param content
     * @return Long Absolute value of Long for the HashCode.
     */
    public static Long getAbsMurmur128HashAsLongVal(String content) {
        return Math.abs(getMurmur128Hash(content).asLong());
    }

【讨论】:

    【解决方案2】:

    Object.hash() 有一个非常简单的 hashCode,对于简单的例子来说这并不是特别统一的。例如Objects.hash("B", "B") 和 Objects.hash("A", "a") 具有相同的 hashCode。 (顺便说一句,很简单,我可以在脑海中解决这个问题)

    Objects.hashCode("a", "a")Objects.hashCode("z", "z") 之间的每一个都介于 4065 和 4865 之间,看起来不是特别均匀,尤其是对于更高的位。

    在这种情况下,我想你可以说你并没有让事情变得更糟。

    【讨论】:

    • 如果是这样。哪种方式更好地避免hashcode()的负值 1. 同上 2. 在这一步避免负值:arr[h+i % h] = k。我的意思是我使用 Math.abs(h+i % h) 转换为正值。
    • @nd07 你想在这里避免Math.abs,因为这会返回一个负数 o_O (hash &amp; 0x7FFF_FFFF) % buckets 更好。注意:Math.abs(Integer.MIN_VALUE) == Integer.MIN_VALUE 很长一段时间你都不太可能发现。
    猜你喜欢
    • 2011-04-04
    • 2011-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多