散列算法和HashMap

时间:2013-09-24 22:00:38

标签: java hash hashmap

在stackoverflow和web中有几个主题,我无法清楚地理解它们。我在尼克拉斯的堆栈流程中找到了这个答案,他的代表性让我对这个主题有了一些有意义的见解。

一些ASCII艺术

key.hashCode()
     |
     | 32-bit value
     |                          hash table
     V                        +------------+    +----------------------+
HashMap.hash() ----+          | reference  | -> | key1 | value1 | null |
                   |          |------------|    +----------------------+
                   |          | null       |
                   | offset   |------------|    +---------------------+
                   +--------> | reference  | -> | key1 | value1 | ref |
                              |------------|    +---------------------+
                              |    ....    |                       |
                                                  +----------------+
                                                  V
                                                +----------------------+
                                                | key2 | value2 | null |
                                                +----------------------+

What hashing function does Java use to implement Hashtable class?

Map aMap = new HashMap();
aMap.put(key,value);
  1. 任何人都可以解释一下`什么是抵消及其价值?哪里 映射的偏移值?。
  2. 什么是哈希表?它是一个对象数组吗?如果是这样的话 对象有一个键,值1和一个参考属性?。
  3. 任何人都可以一步一步地重新解释上面的图表。我无法理解HashMap背后的哈希机制。

1 个答案:

答案 0 :(得分:5)

首先,让我解释一下哈希搜索的想法:

  1. 让您有一些搜索关键。例如,key只是文本字符串,如“hello”。

  2. 让我们为这个字符串计算一些“校验和” - 举个简单的例子 将符号的ASCII码加在一起。让我们(例如,我实际上没有计算) 这笔钱是1009。

  3. 让我们拥有固定大小的数组,例如,SZ = 10。将此数组命名为“hash_table”。 每个数组元素都包含BUCKET - 这是一组可能的键。

  4. 因此,我们可以通过以下方式计算OFFSET - 数组中的索引,即哈希表:

    偏移=总和%SZ = 1009%10 = 9;

  5. 让我们通过以下方式将“hello”这个词存入街头车#9中。

    hash_table [9] .add_to_list( “你好”);

  6. 在那里,我们只有单个键“hello”,存储在单元格hash_table [9];

    1. 想象一下,需要插入第二个键,例如“world”。让我们计算总和,它 将再次计算偏移= 37%10 = 7.因此,通过该算法,我们存入 将“世界”改为哈希表[7]。

    2. 碰撞。想象一下,你决定添加第三个字键,“碰撞”让这个单词的总和为3007.当你计算偏移时,它将是7.因此,单词“collision”必须存入桶中,其中已经存在的单词“世界”。还行吧。您只需将带有世界“碰撞”的元素添加到链接列表(头部或尾部)中。所以:

      哈希表[7] - > “世界” - > “collistion” - >空值; 哈希表[9] - > “你好” - > NULL;

    3. 当您需要搜索“hello”键时,再次计算校验和,它再次为1009.此后,您计算offset = 9,然后直接转到#9桶。并且,迭代链接列表,在那里你会找到你的单词“你好”。 “世界”或“碰撞”的类似情况。

    4. 当您搜索表格中省略的单词时,您将转到空桶或不包含密钥的存储桶。所以,搜索不成功。

      如果你使哈希表太宽(例如,大小与你的字典相同),平均桶大小将是~1个元素(如果哈希函数具有良好的传播)。因此,搜索密钥会很快 - 只需计算hashsum,转到存储桶,并在存储桶中迭代1-2个元素。

      第二 - 我会回答你的问题:

      1. 偏移 - 只是数组中的索引。数组是一个“哈希表”。每个数组元素都包含指向链表的指针,包含存储在同一存储桶中的密钥。

      2. 存储桶方案中的
      3. 哈希表 - 只是数组,包含指向存储桶头的指针。使用另一种散列方案(例如,多次散列等) - 它可以包含自己的对象,而不包含链接列表。