Java 为什么resize的实现方式是这样的?

Java 为什么resize的实现方式是这样的?,java,dictionary,hashmap,resize,Java,Dictionary,Hashmap,Resize,在添加新的键值对时,我有几个关于重建哈希映射的问题。我将根据这些事实提出问题(它们对于Oracle JVM是正确的,不确定它们对于其他JVM是否正确): 调整大小将重建HashMap,以便在每次将HashMap增大到大于阈值(阈值=加载因子*numberOfEntries)时,都具有更大的内部表数组。将新创建的条目放在哪个桶中并不重要,Map仍然会变得更大。即使所有条目都进入一个bucket(即它们的键“hashCode()返回相同的数字) HashMap在删除数据时不会收缩。即使从HashMa

在添加新的键值对时,我有几个关于重建哈希映射的问题。我将根据这些事实提出问题(它们对于Oracle JVM是正确的,不确定它们对于其他JVM是否正确):

  • 调整大小将重建
    HashMap
    ,以便在每次将HashMap增大到大于阈值(阈值=加载因子*numberOfEntries)时,都具有更大的内部表数组。将新创建的条目放在哪个桶中并不重要,Map仍然会变得更大。即使所有条目都进入一个bucket(即它们的键“
    hashCode()
    返回相同的数字)
  • HashMap
    在删除数据时不会收缩。即使从
    HashMap
    中删除了所有键,其表的内部大小也不会改变
  • 现在问题是:

  • 这些事实正确吗
  • 如果是,则:

  • 为什么要采用这种方式?即使在显然不必要的情况下,是否打算扩大内部表?还是虫子
  • 为什么它不收缩

  • 是的,这些事实是正确的

  • 检测是否“显然没有必要”需要花费大量时间,而且几乎总是冗余的,因为所有密钥都具有相同哈希代码的情况很少见。简言之,在极为罕见的情况下,为了节省一些工作,您为每个人都付出了巨大的费用(跟踪某个特定哈希代码的使用情况),这将导致成本高于节省
  • 因为删除是一种不太常见的操作,通常会在重新填充贴图之后进行。如果您想用一个较小的表重新开始映射,您可以将它分配给一个
    新的HashMap
    ,然后让旧的HashMap被垃圾收集

  • 哇,这很合理,谢谢!我能再问一个吗?为什么我们不能在添加表bucket时增长hashmap,而在添加条目时却不能增长hashmap?这个问题没有意义。“添加了表bucket”是“hashmap增长”的同义词;当有更多条目时,会添加表bucket。对不起,“添加表bucket”的意思是“内部表数组已填充”。我的意思是,为什么我们不在所有表数组元素都不为null(或它们的一小部分)时调整映射的大小呢?通过在添加条目时调整大小,我们实际上是在每个bucket的平均条目数超过一定数量时调整表的大小。实际上,原始表中的每个桶在新表中被分成两个桶,其中(平均)一半在一个新桶中,另一半在另一个桶中。有多少bucket是非空的并不重要,重要的是每个bucket的平均条目数。