关于数据结构:Java Key-Value Collection,复杂度为O(1),适用于数百万随机无序密钥

Java Key-Value Collection with complexity of O(1) for millions of random unordered keys

我遇到了一个问题,即我需要随机使用密钥(而不是使用迭代器)来访问数百万个键值对。

在编译时不知道密钥的范围,但是已知密钥值对的总数。

我已经研究过HashMap和Hashset数据结构,但它们并不是真正的O(1),因为在哈希码中发生冲突的情况下它们变成了LinkedLists的数组,在最坏的情况下它具有线性搜索复杂性。

我还考虑过增加HashMap中的桶数,但不能确保每个元素都存储在一个单独的桶中。

有没有办法存储和访问具有O(1)复杂性的数百万个键值对?

理想情况下,我希望每个键都像一个变量,相应的值应该是分配给该键的值

提前致谢。


我认为你在混淆Big O符号代表什么。它定义了函数的限制行为,不一定是实际行为。

对于插入,删除和搜索操作,哈希映射的平均复杂度为O(1)。这是什么意思?平均而言,无论哈希映射的大小如何,这些操作平均都将在恒定时间内完成。因此,根据地图的实现,查找可能不会只采取一步,但相对于哈希映射的大小,它很可能不会涉及多个步骤。

哈希映射对这些操作的实际行为有多好,取决于几个因素。最明显的是用于桶密钥的哈希函数。哈希函数在哈希范围内更均匀地分布计算的哈希值,并且优先限制冲突的数量。这些区域中的散列函数越好,散列映射将在恒定时间内实际操作得越近。

影响实际哈希映射行为的另一个因素是如何管理存储。在添加和删除项目时,地图如何调整大小和重新定位条目有助于通过使用最佳数量的桶来控制哈希冲突。有效地管理哈希映射存储将允许哈希映射在接近恒定时间的情况下运行。

尽管如此,有一些方法可以构造具有O(1)查找最坏情况行为的哈希映射。这是使用完美的哈希函数完成的。完美的哈希函数是键和哈希之间的可逆1-1功能。利用完美的散列函数和适当的散列映射存储,可以实现O(1)查找。使用此方法的先决条件是提前了解所有键值,以便可以开发完美的哈希函数。

遗憾的是,您的情况不涉及已知密钥,因此无法构建完美的哈希函数,但可用的研究可能会帮助您为您的案例构建近乎完美的哈希函数。


不,通用数据类型没有这种(已知的)数据结构。

如果有的话,它很可能已经替换了大多数常用库中的哈希表,除非有一些显着的缺点,如大量的常数因子或荒谬的内存使用,其中任何一个都可能使它对你来说也不可行。

我上面说过"通用数据类型",因为可能存在一些特定的特殊情况,例如当键是小范围内的整数时 - 在这种情况下,你可以只有一个数组,其中每个索引对应于相同的密钥,但这也是一个哈希表,其中密钥哈希自己。

请注意,您需要一个糟糕的哈希函数,哈希函数的病态输入,或者一个非常小的哈希表,以实际获得哈希表的最坏情况O(n)性能。在你去寻找别的东西之前,你真的应该测试一下它是否足够快。您也可以尝试TreeMap,它的O(log n)操作有时会胜过HashMap