Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 哈希表中的哈希函数与哈希映射?_Java_Algorithm_Hash_Hashmap_Hashtable - Fatal编程技术网

Java 哈希表中的哈希函数与哈希映射?

Java 哈希表中的哈希函数与哈希映射?,java,algorithm,hash,hashmap,hashtable,Java,Algorithm,Hash,Hashmap,Hashtable,我知道Hashtable和HashMap之间的区别。然而,这两个类似乎都在使用散列函数来完成任务。Hashtable中使用的哈希函数与HashMap中使用的哈希函数之间是否存在差异 特别是,他们使用的散列算法之间有什么区别吗?这两个类中用于散列的公式是什么 换句话说,计算索引(散列值)的方法不同吗?java.util.Hashtable类似于java.util.Vector。它是在开发早期添加到SDK中的一个类,已被HashMap取代(如ArrayList取代Vector) 因此,除非需要隐式同

我知道Hashtable和HashMap之间的区别。然而,这两个类似乎都在使用散列函数来完成任务。Hashtable中使用的哈希函数与HashMap中使用的哈希函数之间是否存在差异

特别是,他们使用的散列算法之间有什么区别吗?这两个类中用于散列的公式是什么

换句话说,计算索引(散列值)的方法不同吗?

java.util.Hashtable
类似于
java.util.Vector
。它是在开发早期添加到SDK中的一个类,已被
HashMap
取代(如
ArrayList
取代
Vector

因此,除非需要隐式同步所有操作(默认情况下是
Hashtable
),否则不应该使用它,但您仍然可以使用
集合。synchronizedMap
ConcurrentHashMap

如Javadoc中所述:

从Java2平台v1.2开始,该类经过了改造,实现了
Map
接口,使其成为Java集合框架的成员。与新的集合实现不同,
哈希表
是同步的。如果不需要线程安全实现,建议使用
HashMap
代替
Hashtable
。如果需要线程安全的高并发实现,则建议使用
ConcurrentHashMap
代替
Hashtable

这两个类的散列应该相同,因为它们都将使用
int Object::hashCode

特别是,他们使用的散列算法之间有什么区别吗?这两个类中用于散列的公式是什么

将对象用作哈希表键时使用的主要哈希函数是对象的
hashCode()
方法。由key类来实现一个合适的散列函数

Hashtable
HashMap
类获取键的hashcode值,并将其转换为链的主Hashtable数组中的索引。但是,在
Hashtable
HashMap
之间发生这种情况的方式有所不同

  • 对于哈希表(Java 8),代码如下:

     hash = key.hashCode();
     index = (hash & 0x7FFFFFFF) % tab.length;
    
  • 对于
    HashMap
    (Java 8),代码(实际上)如下:

如您所见,
HashMap
正在对键的hashcode函数返回的hashcode值进行置乱。这在源代码中解释如下:

[此方法]计算key.hashCode()并将散列的高位(XOR)扩展到低位。由于该表使用两个掩码的幂,因此仅在当前掩码上方的位上变化的哈希集将始终冲突。(已知的例子中有一组在小表格中保存连续整数的浮点键。)因此,我们应用了一种向下传播高位影响的变换。在比特传播的速度、效用和质量之间存在一种折衷。由于许多常见的散列集已经合理分布(因此无法从传播中获益),并且由于我们使用树来处理容器中的大型冲突集,因此我们只需以最便宜的方式对一些移位位进行异或,以减少系统损失,以及合并最高位的影响,否则,由于表边界,最高位将永远不会用于索引计算

注:

  • &
    %
    的区别在于,在
    哈希表中,哈希数组大小是一个素数,而在
    哈希映射(Java8)中,哈希数组大小是2的幂

  • 在Java8
    HashMap
    中,如果键类实现了
    Comparable
    ,那么实现将把一个长的哈希链变成一个二叉树

  • HashMap
    处理
    null
    键,但
    Hashtable
    不处理


  • 然而,
    HashMap
    中所有这些额外的复杂性只有在密钥类的
    hashCode()
    方法设计/实现不好时才会发挥作用。。。或者如果有人故意试图设计散列冲突


    换句话说,如果您的键类设计得很好,那么差异应该无关紧要。

    可能的重复在最后,两者都使用添加到集合中的对象的
    hashCode()
    。因此,确定“hash”的算法取决于如何在添加的对象上实现
    hashCode()
    。(或者它通常是如何在对象上实现的)实际上,对于Java8来说,算法(明显)不同;看看我的答案。@Tibrogargan我不认为这是那个问题的重复。至少我在这里看不到我的答案。例如,在ArrayList中,当容量达到时,数组的大小乘以1.5;然而,在向量中,这个比率是2。因此,它们并不完全相同。这并不重要。@A.Mashreghi这是一个实现细节,为什么它会让你担心?实际上,对于Java 8来说,算法(明显)不同;请参阅我的答案。@A.Mashreghi-可以说,这与散列算法没有区别。相反,这是调整大小算法的不同之处。
     // (I have restructured the code for ease of comparison.)
     int h;
     hash = (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
     index = (tab.length - 1) & hash;