为什么要rehash?
扩展或是收缩哈希表需要进行rehash操作,rehash的动作不是一次性,集中式的完成,而是分多次,渐进式的完成。
为什么要分多次,渐进式的完成呢?
如果哈希表里保存的键值对数量有几百万,几千万甚至更多时,那么一次性将这些键值对全部rehash到ht[1]的话,庞大的计算量可能会导致服务器在一段时间内停止服务。
渐进式rehash的步骤:
- 为ht[1]分配空间,这时字典同时持有ht[0]和ht[1]两个哈希表;
- 设置索引计数器变量rehashidx = 0,表示rehash工作正式开始;
- 每次对字典执行添加,删除,查找或是更新操作时,除了执行指定的操作以外,还会顺带将ht[0]哈希表在rehashidx索引桑得所有键值对rehash到ht[1],当rehash工作完成之后,程序将rehashidx属性得值增1;
- 随着字段操作得不断执行,最终在某个时间点上,ht[0]的所有键值对都被rehash到ht[1]时,会将rehashidx属性的值设为-1,表示rehash操作已完成。
在渐进式rehash的过程中,字典会同时使用ht[0]和ht[1]两个哈希表,字典的删除,查找,更新等操作会在两个哈希表上进行,例如,要在字典里面查找一个键,程序会先在ht[0]里面查找,如果没有的话,就会继续到ht[1]里面查找。同时新添加的键值对一律会保存到ht[1]里面,ht[0]则不再进行任何添加操作,这一措施保证ht[0]里的键值对数量会只减不增;