为啥 HashMap 和 Hastable 的 put 方法有区别?

Posted

技术标签:

【中文标题】为啥 HashMap 和 Hastable 的 put 方法有区别?【英文标题】:Why there is difference in HashMap and Hastable method of put?为什么 HashMap 和 Hastable 的 put 方法有区别? 【发布时间】:2013-12-12 17:13:05 【问题描述】:

我想知道HashMapHashtableput 方法的区别

HashTableput方法代码

Entry tab[] = table;
     int hash = key.hashCode();
     int index = (hash & 0x7FFFFFFF) % tab.length;
     for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) 
         if ((e.hash == hash) && e.key.equals(key)) 
             V old = e.value;
             e.value = value;
             return old;
         
     

HashMapput方法代码

int hash = hash(key.hashCode());
     int i = indexFor(hash, table.length);
     for (Entry<K,V> e = table[i]; e != null; e = e.next) 
         Object k;
         if (e.hash == hash && ((k = e.key) == key || key.equals(k))) 
             V oldValue = e.value;
             e.value = value;
             e.recordAccess(this);
             return oldValue;
         
     

为什么哈希表有不同的查找索引的代码?

int index = (hash & 0x7FFFFFFF) % tab.length;

而 hashMap 有 jdk 设计者提供的hash() 函数。

【问题讨论】:

hash() 函数对 hashmap 所做的同样的事情 两者都通过调用hashCode 来获取哈希值。不同之处在于调用indexFor 方法。你知道这个方法是做什么的吗?不只是执行有问题的线路吗? 因为有。 Hashtable 写于 1995 年左右,HashMap 写于 1997 年左右,并非完全是同一个人。除了意见之外,您必须要求作者获得任何信息。 但无论如何他们提供更新,所以他们不能修改哈希表类吗? 当然可以。为什么你认为他们应该这样做? 【参考方案1】:

二进制中的0x7FFFFFFF 是什么?我是01111111111111111111111111111111

注意最左边的0。这意味着该数字总是为正数(因为最左边的 bit 为零)。由于&amp;,每个将被&amp;-ed 这个二进制文件的数字都将是非负数,因为:

01111111111111111111111111111111
Anything                          &
--------------------------------
0 ← Always

在此之后,% 运算符用于确保我们在tab.length 的范围内。

您没有发布HashMap 如何生成索引的实现。我不认为这是非常不同的。毕竟他们的逻辑非常相似。

HashMap 调用 indexFor 正在做的事情:return h &amp; (length-1);

重要提示:HashTableHashMap 旧,难怪有不同的实现。

【讨论】:

【参考方案2】:

哈希表:

int index = (hash & 0x7FFFFFFF) % tab.length;

这意味着: 哈希 - 没有最左边的位(符号)以表长度为模

哈希映射:

int i = indexFor(hash, table.length);

正在打电话:

static int indexFor(int h, int length) 
   return h & (length-1);

表示模长度-1 那里差别不大,实际上modulo length-1 意味着我们可以获得的最大值是长度为2。在这里,length-1 确保我们不会遇到我们会得到0xFFFFFFFF 的情况,实际上我们可能得到的最高值将是0xFFFFFFFE

区别在于低位(在 HashMap 中与 HashTable 中的高位)。现在我们应该(递归地)问为什么会这样。答案隐藏在代码第一行(上图)中出现的 hash() 方法中,该方法也与 HashTable 实现不同:

int hash = hash(key.hashCode());

解释在hash() method:

           /**
  258      * Applies a supplemental hash function to a given hashCode, which
  259      * defends against poor quality hash functions.  This is critical
  260      * because HashMap uses power-of-two length hash tables, that
  261      * otherwise encounter collisions for hashCodes that do not differ
  262      * in lower bits. Note: Null keys always map to hash 0, thus index 0.
  263      */
  264     static int hash(int h) 
  265         // This function ensures that hashCodes that differ only by
  266         // constant multiples at each bit position have a bounded
  267         // number of collisions (approximately 8 at default load factor).
  268         h ^= (h >>> 20) ^ (h >>> 12);
  269         return h ^ (h >>> 7) ^ (h >>> 4);
  270     
  271 

【讨论】:

以上是关于为啥 HashMap 和 Hastable 的 put 方法有区别?的主要内容,如果未能解决你的问题,请参考以下文章

第13题-HashMap和HashTable的区别

面试官:你说 HashMap 线程不安全,它为啥不安全呢?

TreeMap和Comparable接口

hashset hastable dictionary concurrentdictionary区别

python 实现一个简单的hastable及其操作。

《C#零基础入门之百识百例》(八十七)系统类HasTable哈希表解析 -- 几种遍历方式