【问题标题】:Simple hash function techniques简单的散列函数技术
【发布时间】:2024-09-18 12:25:02
【问题描述】:

我对 Java 中的散列还很陌生,而且我一直卡在几个部分上。我有一个包含 400 个项目的列表(并存储在 1.5x = 600 的列表中),其中项目 ID 的范围为 1-10k。我一直在研究一些散列函数,我最初复制了数据包中的示例,它只是使用了折叠。我注意到我得到了大约 50-60% 的空节点,这显然太多了。我还注意到,仅将 id 修改 600 往往会将其减少到固定的 50% 空值。

我当前的哈希函数看起来像这样,因为它很丑陋,它从简单的修改中减少了 1% 的空值,平均列表长度为 1.32...

   public int getHash( int id )
   {
      int hash = id;

      hash <<= id % 3;
      hash += id << hash % 5;

      /* let's go digit by digit! */          
      int digit;
      for( digit = id % 10;
           id != 0;
           digit = id % 10, id /= 10 )
      {
         if ( digit == 0 ) /* prevent division by zero */
            continue;
         hash += digit * 2;
      }

      hash >>= 5;
      return (hash % 600);
   }

创建简单散列函数有哪些好的技巧?

【问题讨论】:

    标签: java hashtable


    【解决方案1】:

    我会保持简单。将元素的id 作为哈希码返回,并让哈希表担心如果需要重新哈希它。 您的目标应该是为您的对象创建唯一的哈希码

    Java HashMap 使用以下重新散列方法:

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

    【讨论】:

      【解决方案2】:

      有一篇很好的评论文章here。此外,Wikipedia article on hash functions 是一个很好的概述。它建议使用卡方检验来评估哈希函数的质量。

      【讨论】: