Java HashTable/HashMap是数组吗?

Java HashTable/HashMap是数组吗?,java,hash,hashmap,hashtable,Java,Hash,Hashmap,Hashtable,我对散列法感到困惑: 当我们使用Hashtable/HashMap(key,value)时,首先我理解了内部数据结构是一个数组(已经在内存中分配) Java hashcode()方法有一个int返回类型,所以我认为这个散列值将用作数组的索引,在本例中,我们应该在RAM中的数组中有2个幂32项,这不是实际发生的情况 那么Java是否从范围较小的hashcode()创建索引呢 回答: 正如下面和文档中提到的: HashMap是一个数组。hashcode()再次被重置,但仍然是整数,数组中的索引变为:

我对散列法感到困惑:

当我们使用Hashtable/HashMap(key,value)时,首先我理解了内部数据结构是一个数组(已经在内存中分配)

Java hashcode()方法有一个int返回类型,所以我认为这个散列值将用作数组的索引,在本例中,我们应该在RAM中的数组中有2个幂32项,这不是实际发生的情况

那么Java是否从范围较小的hashcode()创建索引呢

回答:

正如下面和文档中提到的:


HashMap是一个数组。hashcode()再次被重置,但仍然是整数,数组中的索引变为:h&(length-1);因此,如果数组的长度是2^n,那么我认为索引从重新散列的值中获取第一个n位

通常,基本数据结构实际上是一个数组

需要查找条目(或在添加新对象的情况下为空间隙)的方法会将哈希代码减少到适合数组大小的值(通常通过模),并将其用作该数组的索引

当然,这使得发生冲突的可能性更大,因为许多对象可能有一个减为相同索引的哈希代码(无论如何都有可能,因为多个对象可能有完全相同的哈希代码,但现在可能性更大)。处理这个问题有不同的策略,通常可以使用类似链表的结构,或者如果匹配的第一个插槽被非相等键占用,则可以使用一种机制来选择另一个插槽

因为这增加了成本,所以发生这种冲突的频率越高,事情就变得越慢,在更糟糕的情况下,查找实际上是O(n)(并且也会随着O(n)的变化而变慢)

但是,增加内部存储的大小通常会改善这一点,特别是当它不是以前大小的倍数时(因此减少哈希代码以查找索引的操作不会让一堆项目在同一索引上发生冲突,然后再次为它们提供相同的索引)。在某些情况下(某些百分比、与不具有相同完整哈希代码的对象的碰撞次数等),某些机制会在绝对必要之前增加内部大小(同时还有一些剩余的空白空间)


这意味着,除非哈希代码非常糟糕(最明显的是,如果它们实际上完全相同),否则操作顺序保持在O(1)。

Java
哈希映射的结构不仅仅是一个数组。它是一个数组,但不是由
2^31
条目组成(
int
是一种有符号类型!),而是由一些较小数量的bucket组成,默认情况下,最初为
16
HashMap
的Javadocs解释了这一点

当条目数超过容量的某一部分(“负载系数”)时,阵列将变大

数组中的每个元素不仅仅包含一个条目。数组中的每个元素都包含一个条目结构(当前是一个红黑树,以前是一个列表)。结构中的每个条目都有一个哈希代码,该代码在内部转换为数组中相同的存储桶位置

你看过这种类型的文件了吗?


您确实应该这样做。

谢谢Jon的回复。让我们以Java hashcode()方法为例。此方法返回int。这是否意味着HashMap(将使用此方法)将生成一个包含2个幂32项(4千兆项)的数组在RAM中。如果不是这样的话,为什么返回类型是int,最好是byte/short类型。它将以较小的大小开始,但根据需要变大。对于40亿个可能的值,都会产生较大的最大大小,并且也使得当模降到较小的大小时,两个项每次都发生冲突的可能性较小。这是合理的e、 Jon+1标准Java API没有
HashTable
类型。您的意思是
HashTable
?@LewBloch yes HashTable”在Java hashcode()方法中有一个int返回类型,因此理论上我们应该为RAM中的数组保留2个32次方(即4个千兆条目)“-我看不出你的理由。@JonSkeet嗨。请检查上面的更新。更新没有解释为什么您认为内部阵列的大小必须是2^32。你的“理论上如此”暗示了一个你没有解释的逻辑步骤(这是不正确的)。谢谢卢。因此,如果HashMap使用的bucket数小于2^31,这意味着hashcode()方法返回的int hash值将再次进行散列,以适应范围,例如默认情况下为16,请更正我的错误?如果是这种情况,当前使用的将int散列值重新散列为较小值(是简单模)的方法/算法是什么?@MosabShaheen为什么不阅读HashMap的文档和源代码?它是免费的,并与您的JDK捆绑在一起。@JBNizet谢谢。hashcode()再次被重置,但仍然为int,数组中的索引变为:h&(length-1);因此,如果数组的长度是2^n,那么我认为索引从重新散列的值中获取第一个n位。这是合理的,刘易斯+1