有关java.util.Hashtable的实现细节的查询

时间:2015-12-02 18:04:11

标签: java hashtable

我有关于java.util.Hashtable如何的以下查询 实现。这些是低级查询,与Hashtable的使用无关,但仅与设计人员如何选择实现数据结构有关

  • 使用默认大小11个桶创建Hashtable。 11有什么特别之处?为什么不10?虽然我倾向于认为这只是一个神奇的数字,但我认为不太好。
  • 要计算存储桶编号,为什么我们不直接使用传入的密钥对象的哈希码。在实现中,我们实际上将桶号计算为(hashcode& 7FFFFFFF)%表大小,其中 hashcode 是输入键的返回值,表大小默认为11 。为什么我们重新编写哈希码本身?难道它不只是哈希码%table size?
  • contains(Object value)方法搜索哈希表中是否存在值。为此,我们从最后一个桶顺序搜索并向第一个桶移动。这只是采用的开发者风格吗?哈希表只是一个链表的数组。更直观地说,我希望搜索从第一个桶移动到最后一个桶,但不然发现了。我知道功能上两者都是一样的。但还有其他原因吗?
  • 最大数组大小(在重新散列期间使用)设置为Integer.MAX - 8. 8这里有什么意义?

2 个答案:

答案 0 :(得分:2)

  1. 这似乎是一个经验值,涉及在使用太多空间和浪费时间的重复操作之间进行权衡。 Hashtable javadocs
  2.   

    初始容量控制了浪费空间与重新运算操作需求之间的权衡,这是非常耗时的。如果初始容量大于Hashtable将包含的最大条目数除以其加载因子,则不会发生重复操作。但是,将初始容量设置得太高会浪费空间。

    1. 使用0x7FFFFFFF对值进行位掩码,以删除使值为负的第一位。这会强制该值为非负值,因此%操作后的结果索引也将为非负值。这对于在内部桶阵列中生成可行索引是必要的。

    2. 这样做可能会略微提高性能。 This article claims that looping backwards does exactly that.

    3.   

      结果表明,在100万个数据中,正向和反向循环之间差别不大。然而,当数据量增长时,反向循环的性能比前向循环的性能略快15%左右。

      我不知道这是否真的如此,但这可能是动机。

      1. 我的源代码揭示了用于最大数组大小的私有常量的Javadoc。
      2. /**
         * The maximum size of array to allocate.
         * Some VMs reserve some header words in an array.
         * Attempts to allocate larger arrays may result in
         * OutOfMemoryError: Requested array size exceeds VM limit
         */
        private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
        

        我不知道现在有多有效,但这是为了避免意外OutOfMemoryError

答案 1 :(得分:1)

#1:AndreyS在评论中回答:Why initialCapacity of Hashtable is 11 while the DEFAULT_INITIAL_CAPACITY in HashMap is 16 and requires a power of 2

#2:在计算模数之前确保数字为正。否则结果可能是负面的,我们将超出界限。

#3:我必须猜测,当反向循环时,你只评估一次长度,并与常量(0)进行比较,并在常规循环中与变量进行比较。我不知道这是否是他们心中的想法,但这可能是一个考虑因素。

#4:为避免rehash()中的整数溢出:

int i = table.length;
Entry[] arrayOfEntry1 = table;
int j = (i << 1) + 1;
if (j - 2147483639 > 0)
{
  if (i == 2147483639) {
    return;
  }
  j = 2147483639;
}