在HashMaps中用O(1)时间插入/删除数百万个对象(具有不同的键)?

时间:2017-04-14 23:59:17

标签: java data-structures hashmap

我知道插入/删除在O(1)时间内使用Java HashMaps。

但是如果我的HashMap中有超过一百万个对象(具有不同的键 - 即每个对象都有一个唯一的键),它仍然是最快的数据结构吗?

2 个答案:

答案 0 :(得分:2)

TL; DR - 描述您的代码!

HashMap插入和删除的平均性能缩放为O(1)(假设您在键 1 上有一个声音hashCode()方法),直到您开始运行到第二 - 记忆效应:

  • 堆越大,垃圾收集所需的时间越长。通常,影响最大的因素是非垃圾对象的数量和大小。足够大的HashMap会做到这一点......
  • 您的硬件物理内存有限。如果您的JVM内存需求增长超过该值,主机操作系统将在RAM和磁盘之间“交换”内存页。如果您的堆大小大于JVM进程可用的物理RAM量,那么足够大的HashMap将会这样做。
  • 由于处理器的内存缓存大小和TLB缓存大小而导致内存效应。基本上,如果处理器在读写内存中“需求”太大,则内存系统成为瓶颈。大堆和高度非本地化的访问模式可能会加剧这些影响。 (并运行GC!)

HashMap的主哈希数组的大小也有约2 ^ 31的限制。因此,如果您有超过大约2 ^ 31 / 0.75个条目,则理论上HashMap实现的性能O(N)。但是,我们正在谈论数十亿的条目,并且二阶记忆效应将在此之前影响性能。

1 - 如果您的密钥具有较差的hashCode()功能,那么您可能会发现您将相当大比例的密钥散列到相同的代码中。如果发生这种情况,这些密钥的查找,插入和删除性能将是O(logN)O(N) ...取决于密钥的类型和Java版本。在这种情况下,N是表中的数字键,其哈希码与您正在查找的哈希码相同,等等。

HashMap是用例的最快数据结构吗?

  • 如果没有更详细的用例,很难说。
  • 如果不了解您准备投入多少时间和精力,很难说。 (如果你付出了足够的编码努力,你几乎可以肯定地减少几个百分点。也许更多。HashMap是通用目的。)
  • 如果没有你(首先!)进行适当的性能分析,很难说。

例如,您首先需要确保HashMap确实是导致性能问题的原因。当然,你>>想<<它是,但你有没有实际剖析你的代码找出来?在你这样做之前,你可能会浪费时间去优化不是瓶颈的东西。

答案 1 :(得分:0)

因此即使对于大量对象,HashMaps也会有O(1)插入/删除。大量数据的问题在于空间。对于一百万个条目,你可能在内存中很好。

对于HashMap,Java的默认加载因子为.75,这意味着HashMap需要133万个插槽才能支持此映射。如果你能在记忆中支持这一点,那一切都很好。即使你不能把这一切都记在内存中,你可能仍然想要使用HashMaps,也许是Distributed HashMap

就Big-O时间而言,这是指最坏情况的复杂性。只有当数据大小变得越来越大时,分析Big-O时间才真正有用。如果您使用的是非常小的数据集,则O(5n + 10)与O(n)不同。恒定时间(O(1))时间如此有价值的原因是因为它意味着时间不依赖于数据集的大小。因此,对于像您所描述的那样的大型数据集,由于插入/删除的时间恒定,HashMap将是一个很好的选择。