虽然客观回答这个问题的唯一方法是进行性能测试,但我会主张使用 Hashtable Map。(缓存和内存访问可能充满惊喜;我没有专业知识来推测哪个会更快,什么时候更快。还要考虑到本地化的性能差异可能会被其他代码边缘化。)
我“最初选择”哈希的第一个原因是基于观察到有 100M 不同的键但只有0.1M 活动记录。这意味着如果使用数组,索引利用率将仅为 0.1% - 这是一个非常稀疏的数组。
如果数据作为值存储在数组中,那么它需要相对较小,否则数组大小会膨胀。如果数据未存储在数组中(例如,数组是指针),则数组中数据的局部性参数会部分减轻。无论哪种方式,简单的数组方法都需要大量未使用的空间。
由于所有的键已经是整数,分布(散列)函数可以有效地实现——不需要创建复杂类型/序列的散列,所以这个函数的“成本”应该接近于零。
所以,我提出的简单哈希:
- 使用由连续内存支持的线性探测。它简单,具有良好的局部性(尤其是在探测期间),并且避免了需要进行任何形式的动态分配。
- 选择一个合适的初始桶大小;比如说,2x(或 0.2M 个桶,已准备好)。甚至不要给哈希调整大小的机会。请注意,这个建议的桶数组大小仅为简单数组方法大小的0.2%,并且可以进一步减小,因为可以调整大小与碰撞率。
- 为哈希创建一个良好的分布函数。它还可以利用 ID 范围的知识。
虽然我已经为给定的情况提供了“优化”的专门哈希表规则,但我将从普通的 Map 实现(无论是哈希表还是树)开始并对其进行测试。如果标准实现工作得很好,为什么不使用它呢?
现在,在预期和极端负载下测试不同的候选人 - 并挑选获胜者。