当大小超过最大阈值时,如何在hashmap或hashtable中完成重新散列过程?
是否所有对都只是复制到一个新的桶数组中?
编辑:
重新散列后,同一个桶(链表中)中的元素会发生什么?我的意思是重新散列后它们会保留在同一个桶中吗?
问题中的最大阈值称为负载因子。
负载因子最好在0.75左右。负载因子定义为(m/n),其中n是哈希表的总大小,m是在需要增加底层数据结构大小之前可以插入的首选条目数。
可以在两种情况下进行重新散列:
>
当当前m'/n比增加超过负载因子时
m/n比率下降到非常低的值,比如0.1
在这两种情况下,m'是当前条目的数量。此外,这两种情况都要求将当前条目转移到更大或更小的哈希表中。
在问题的上下文中,重新散列是对条目应用散列函数以将它们移动到另一个哈希表的过程。可以使用之前使用的散列函数或完全使用新函数。
请注意:当碰撞发生时也会进行重新散列。(这也是处理碰撞的一种方式。)
要添加更多上下文和详细讨论,请访问我的博客哈希基础知识
哈希映射的重新散列是在映射中的元素数量达到最大阈值时完成的。
通常负载因子值为0.75,默认初始容量值为16。一旦元素数量达到或超过容量的0.75倍,就会发生map的rehash。在这种情况下,当元素数量为12时,就会发生rehash。(0.75*16=12)
当重新散列发生时,可以使用新的散列函数,甚至可以使用相同的散列函数,但是值所在的桶可能会发生变化。基本上,当重新散列发生时,桶的数量大约增加了一倍,因此必须放置值的新索引会发生变化。
重新散列时,每个桶的链表顺序颠倒。发生这种情况是因为HashMap不会在尾部附加新元素,而是在头部附加新元素。因此,当重新散列发生时,它会读取每个元素并将其插入头部的新桶中,然后继续从新地图头部的旧地图中添加下一个元素,从而导致链表颠倒。
如果有多个线程处理相同的哈希映射,则可能导致无限循环。
说明如何无限循环发生在上述情况下的详细解释可以在这里找到:http://mailinator.blogspot.hu/2009/06/beautiful-race-condition.html
如果映射中插入的元素必须根据键进行排序,那么可以使用TreeMap。但是如果键的顺序无关紧要,HashMap会更有效。
基本上,在创建哈希映射时,集合为其分配了默认容量(2^4,即16。)。后期,当元素添加到映射中时,在某个阶段之后,当您接近初始定义的容量时,需要重新哈希来保持性能。
为集合定义了LoadFactor(据说是.75),这指定了时间和空间的良好索引。
Java规范建议良好负载因子值为.75
因此,假设您有一个最大要求,即在哈希中存储10个元素,那么考虑到良好的负载因子.75=在集合中添加7个元素后会发生重新哈希。如果您的需求在这种情况下不同意7,那么重新哈希将永远不会发生。
如果hashmap中存储的元素真的很多,那么创建具有足够容量的HashMap总是好的;这比让它执行自动重新散列更有效。
竞争条件:当对存储在给定桶的链表中的内部元素进行重新散列时。它们的顺序是相反的。假设有两个线程同时遇到竞争条件,那么在遍历过程中,由于顺序已经改变,第二个线程有可能进入无限循环。