为什么hashmap会根据总大小而不是填充桶来调整大小

时间:2017-11-08 10:13:52

标签: java hashmap

我怀疑自己的想法::

目前,java中的HashMap在totalSize(no of elements inserted) > arrayLength * loadFactor

时调整大小

所以它将表加倍并重新表达所有键值。

但是假设Key类中的hashcode被硬编码为1,所以每次元素都将以链表方式插入索引1。但我们的bucketarray将无需调整总大小。因此,当元素与这样的哈希码实现在同一个桶中时,它将继续增加bucketarray大小。

我有一个问题,如果我们不检查填充桶的大小,而不是总大小?

我知道这样的哈希码会妨碍性能。我认为这是一个合乎逻辑的问题。

3 个答案:

答案 0 :(得分:3)

HashMap有一些代码试图改进错误的hashCode()实现,但它无法改善总是返回相同值的可怕hashCode()实现。

无论您是否调整hashCode()的大小,这样的HashMap都会带来糟糕的表现。因此,HashMap的这种错误使用并不能证明你建议添加特殊逻辑。

密钥的hashCode()实现的假设是它将在HashMap个bin中尽可能接近地均匀分布密钥。因此,存储桶中的平均条目数(即条目总数除以存储桶数)应该可以很好地估计何时应调整HashMap的大小,并且各个存储桶的大小不会很小。 ; t需要检查。

答案 1 :(得分:1)

想象一下大小为12的哈希映射,其中包含9个项目。让我们说巧合的是,#hashCode()只返回3的倍数 - 它仍然是一个有缺陷的哈希码,但它不是一个人为的边缘情况,例如1的常量哈希码。这意味着在这种情况下,只有4个桶(0,3,6和9)将填充1或2个元素。

使用您的方法,此哈希值永远不会调整大小,冲突列表将永远增长,性能将受到影响。但是,如果根据总大小调整大小,加载第十个元素时的加载因子为75%,则最终会得到一个包含24个桶的映射,其中8个将被填充。

基于总大小的增长使冲突列表保持合理的大小并具有逼真的不完美哈希函数,因为期望每个哈希函数至少最佳地尝试分发哈希码是合理的。这意味着增长哈希映射将导致比以前更多的桶,即使可能仍然存在集群和空桶。

基本上,您的建议是在边缘情况下优化内存使用,并且在更可能的情况下不优化访问性能 - 即地图的主要用途。

答案 2 :(得分:0)

如果hashcode始终返回相同的值

  1. 这是一个糟糕的实现,没有支持不应该做的事情的逻辑。

  2. hashcode可能不是常量函数,HashMap无法知道散列函数是否为常量类型,因此调整hashmap的大小是明智的。 hashcode变为非常数函数,然后调整大小可能会更好地分配值。