Java:散列函数

Java:散列函数,java,hash,hashcode,Java,Hash,Hashcode,我想知道,如果我们实现了自己的hashmap,它不使用两个长度哈希表的功能(初始容量和每次调整大小),那么在这种情况下,我们可以直接使用对象的hashcode并修改总大小,而不是使用hash函数对对象的hashcode进行哈希吗 比如说 public V put(K key, V value) { if (key == null) return putForNullKey(value); // int hash = hash(k

我想知道,如果我们实现了自己的hashmap,它不使用两个长度哈希表的功能(初始容量和每次调整大小),那么在这种情况下,我们可以直接使用对象的hashcode并修改总大小,而不是使用hash函数对对象的hashcode进行哈希吗

比如说

   public V put(K key, V value) {
         if (key == null)
             return putForNullKey(value);
         // int hash = hash(key.hashCode());     original way
         //can we just use the key's hashcode if our table length is not power-of-two ?
         int hash = key.hashCode();              
         int i = indexFor(hash, table.length);
         ...
         ...
     }

您可以将mod函数看作是散列函数的一种简单形式。它将大范围的数据映射到较小的空间。假设最初的hashcode设计得很好,我看不出为什么不能使用mod将hashcode转换为您正在使用的表的大小


如果原始的hashfunction没有很好地实现,例如总是返回偶数,那么只使用mod函数作为hashfunction将创建大量冲突。

这是真的,您可以选择伪素数

注意:indexFor需要使用
%
补偿符号,而不是简单的
&
,这实际上会降低查找速度

indexFor = (h & Integer.MAX_VALUE) % length
// or
indexFor = Math.abs(h % length) 

假设我们谈论的是OpenJDK 7,附加的是用来刺激雪崩的;这是一个好主意。之所以使用它,是因为从散列到存储桶的映射函数(因为我们使用2的幂作为容量)仅仅是按位的
&
(因为
a%b
相当于
a&(b-1)
iff
b
是2的幂);这意味着较低的位是唯一重要的位,因此通过应用此混合步骤,它可以帮助防止较差的散列

 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);
 }
如果要使用非2次幂的大小,则可能不需要上述值

实际上,更改从散列到存储桶的映射(通常依赖于容量为2的幂)需要您查看:


您可以在此处使用
(h&0x7fffffff)%length

您需要类似
(h&Integer.MAX_VALUE)%length
Math.abs(h%length)
@PeterLawrey是正确的;您需要确保正确处理负哈希。我想知道如何调整容量。我能把容量乘以素数吗?我知道这可能是不经济的。@user1389813
HashMap
当加载因子要超过阈值时会重新刷新,是的。@user1389813不,不是全部
TreeMap
是使用一个而不是哈希表实现的,因此不使用哈希<但是,code>LinkedHashMap、
HashMap
Hashtable
。如果哈希表变得太满,当操作接近线性时间时,您可能会遇到性能下降。我想知道,如果我们选择伪素数,那么在调整哈希表大小时,是否需要完全重建该表?由于indexFor中的索引现在不同了。您可以进行渐进式重建,但速度较慢(但确实可以避免一次大的命中)。避免这种情况的最简单方法是使映射足够大,从而不会发生这种情况。从性能角度看。Java API中的默认哈希函数(两个长度表的幂)或这种方法哪个更好?
 static int indexFor(int h, int length) {
     return h & (length-1);
 }