hashCode实现策略

时间:2012-04-02 12:12:32

标签: java hashcode

一些主要的JVM类(例如StringList implementations)通过为与Σ 31^n * field_n.hashCode()方法相关的每个field_n返回equals来实现等于。此外,Joshua Bloch在Effective Java(第9项)中推荐了这种方法。

但是,Map.Entry implementations等其他类遵循不同的规则。例如,Map.Entry文档指出Map.Entry的哈希码应该是

 (e.getKey()==null   ? 0 : e.getKey().hashCode()) ^
 (e.getValue()==null ? 0 : e.getValue().hashCode())

这有时在哈希表中使用是不切实际的,因为:

  • 具有相同键和值的所有条目的哈希码为0,
  • 两个条目e1和e2,以便e1.key = e2.value和e1.value = e2.key具有相同的哈希码。

为什么Java选择Map.Entry hashCode的实现规范而不是31 * (e.getKey()==null ? 0 : e.getKey().hashCode()) + (e.getValue()==null ? 0 : e.getValue().hashCode())

修改1:

为了帮助解决问题,下面是一个有用代码的示例,如果许多条目具有相同的键和值,则由于哈希冲突导致结果性能非常差。

此方法计算不同地图条目的频率(使用Guava的Multiset)。

public static <K, V> Multiset<Map.Entry<K, V>> computeEntryCounts(
        Iterable<Map<K, V>> maps) {
    ImmutableMultiset.Builder<Map.Entry<K, V>> result = ImmutableMultiset.builder();
    for (Map<K, V> map : maps) {
        for (Map.Entry<K, V> entry : map.entrySet()) {
            result.add(entry);
        }
    }
    return result.build();
}

2 个答案:

答案 0 :(得分:4)

我怀疑这是一个很好的理由 - 我认为这只是一个疏忽 - 但这并不是一个严重的问题。如果您有HashSet<Map.Entry<T,T>>HashMap<Map.Entry<T,T>,V>,则通常会出现这种情况。 (编辑添加:或者,正如Joachim Sauer在下面指出的那样,HashSet<Map<T,T>>HashMap<Map<T,T>,V> - 也不常见。)

请注意,HashMap<K,V> 使用Map.Entry<K,V>.hashCode(),因为它只按 键查找条目,因此只使用{{1} }}

答案 1 :(得分:0)

我的个人猜测是,hashCode也应该很快。

由于您可以覆盖hashCode,因此没有任何问题。 当你知道一个更适合你案例的算法时,改变它