【问题标题】:HashMap rehashing and its subsequent effect on performance as compared with TreeMap与 TreeMap 相比,HashMap 重新散列及其对性能的后续影响
【发布时间】:2014-04-11 07:37:58
【问题描述】:
HashMap: intialCapacity=1000; loadFactor=0.75; 

上面的意思是,HashMap 将重新调整大约 1000*75 = 750 th entry 到 2000 的大小。此时会进行重新散列吗?如果是,那么性能会受到怎样的影响?如果没有,那么什么时候?在 MAX_CAPACITY?

TreeMap:没有重新散列,而是排序。文档表明插入/读取/搜索始终为 O(log N)。但是,排序/新条目/删除条目不是总是重新调整整个 TreeMap 的大小吗?

就上述场景和整体性能而言,两者在 BigO 表示法方面如何比较?

HashMap 和 ConcurrentHashMap 是高度使用的实现,但相比之下,TreeMap 的使用并不多。我同意只添加和很少删除但经过高度搜索的 TreeMap 最好优于 HashMap/table 实现。

感谢任何评论。

编辑: 在数据结构摊销方面,应该考虑的最佳实践的性能最差情况是什么?就像重新散列基于哈希的 MAP 和/或调整基于树的 Map 或集合的大小。有一定的权衡,但假设由于高度不可预测的吞吐量而不断地要求修改数据结构。

【问题讨论】:

  • 请注意,就大 O 而言,我们不考虑数组调整大小和树重新平衡之类的事情,因为它是一种概括所使用算法类型的方法,并不代表确切的性能。哈希表的插入总是 O(1),红黑树的插入总是 O(log(n))。
  • @Radiodef,了解。但是,这是我正在寻找答案的一块。 Big-O 是算法的最佳方案,但实际上并不理想。当哈希图重新散列和/或树图调整大小以访问/插入/搜索时间时会发生什么?这是我最坏的情况吗?差多少?比较器/可比较的排序或使用是否会生效?什么时候?
  • 嗯,重要的是,就性能而言,哈希表的访问性能将优于任何其他数据结构。在您需要排序的情况下,红黑树将胜过任何其他数据结构。当调整大小/重新排序的东西发生时,你当然会得到一个小小的突突,但大多数数据结构需要不时地做这样的事情。
  • 顺便说一句measurements have been made before on HashMap parameters。它们很难准确量化。
  • 这是一个很棒的链接。感谢您的信息。

标签: java collections


【解决方案1】:

上面的意思是,HashMap 将重新调整大约 1000*75 = 750 th entry 到 2000 的大小。

“大约是桶数的两倍”是 Javadoc 所说的。您正在添加没有保证的精度。

此时会进行重新散列吗?

是的,根据 Javadoc。你好像没看过。

如果是,那么性能会受到怎样的影响?

Javadoc 说将会对整个 HashMap 进行重新散列。这当然是 O(N),但它只是偶尔发生,所以它渐近为零。

如果没有,那么什么时候?在 MAX_CAPACITY?

见上文。

TreeMap:没有重新散列,而是排序。

没有重新散列,也没有排序。只是维护一个有序的数据结构。这不是一回事。

文档表明插入/读取/搜索总是 O(log N)。

文档指定。这不仅仅是一个建议。

但是,sorting/new-entry/delete-entry 不是总是重新调整整个 TreeMap 的大小吗?

不,因为它没有保存在数组中。 Javadoc 说它是作为红黑搜索树实现的。

就上述场景和整体性能而言,两者在 BigO 表示法方面如何比较?

如文件所述。 HashMap 是 O(1),TreeMap 是 O(log N)。

我同意只添加很少删除但经过高度搜索的 TreeMap 最好优于 HashMap/table 实现。

我没有。它不是。

【讨论】:

  • 您的答案很准确,但是,我想,我正在尝试寻找关于重新散列对性能影响的答案。重新散列是一项代价高昂的操作,无论 HashMap 上的 O(1) 性能与否,但是如果在重新散列发生的同时准确地调用 put 操作会发生什么?它仍然是O(1)吗?如何完全避免重新散列?有一个固定大小的 HashMap 知道最大吞吐量吗?你能请。解释“我不知道。不是。”谢谢
  • 重新散列作为看跌期权的结果进行。如果您的意思是两个并发放置,那么无论重新散列如何,行为都是未定义的。您可以通过使初始大小足够大来避免重新散列,但与其过分担心它,我会先做一些测量,看看您是否一开始就有问题。 HashMap 可能会在几分之一秒内重新散列一百万个条目。我不同意在不需要排序的任何情况下,TreeMap 比 HashMap 更可取,除非键 hashCodes 是退化的。
  • 再次感谢您提供详细信息。在我的例子中,当我使用 HashMap 来实现高吞吐量时,比如每秒 50K 条目,重新散列是不可取的,并且由于复制具有新大小的新 Entry 类而导致的潜在 GC 运行也可能会添加到GC的暂停时间。所以,我试图找到一个平衡点,我可以看到我的最大条目在任何给定时间都是 200K,那么您是否同意不会发生重新哈希?对于树形图,不是 O(log n) 通常比 O(1) 快——而且我知道 O(1) 因场景而异。
  • 我认为我们不能避免重新平衡树形图,而是重新散列基于哈希的地图。你同意吗?
  • O(log N) 不可能“通常比 O(1) 快”,除非 log N array 的 Entry 类,是这个意思吗?您可以通过我上面提到的方法避免重新散列。这些天,GC 是并发的。本世纪我还没有看到 GC 暂停。
猜你喜欢
  • 2018-05-01
  • 2018-04-25
  • 1970-01-01
  • 1970-01-01
  • 2015-01-10
  • 2021-10-22
  • 1970-01-01
  • 2012-05-13
  • 1970-01-01
相关资源
最近更新 更多