【问题标题】:Efficient Map for small ranges of integers小范围整数的高效映射
【发布时间】:2013-04-29 19:05:12
【问题描述】:

所以我有一个程序使用许多 HashMaps,这些 HashMaps 存储少量整数键,介于 0 和 50 之间,其键表示小于 100 的唯一序数。

这些地图经常被访问,我已经完成了分析以确定它有助于拥有更高效的数据结构。理想情况下,我会使用类似于 EnumMap 的东西,因为这些整数很小且唯一。

限制:我试图避免使用数组,因为这些映射中的许多只有少数可能的键。我也试图避免使用 3rd 方库。大型库肯定不存在,但小型库或只有 1 或 2 个类可能没问题。

有没有人知道适合这种情况的快速地图?

【问题讨论】:

  • 我看不到任何比 50 元素数组更快的东西。
  • 时间和空间几乎是总是的权衡。 50 个元素的数组非常小。克服它。除非您更改整个方法,否则您不会比单操作码数组索引更快。
  • 对于它的价值,一个 EnumMap 内部只有一个数组,其大小是枚举中元素的数量。
  • 当然,但是您似乎不喜欢 50 元素数组的想法。您暗示您想要与 EnumMap 一样好的东西,但需要整数而不是枚举;我只是指出这是一种错误的二分法,因为包含 50 个元素的枚举的 EnumMap 只是一个 50 个元素的数组。
  • 说“我想要一些比 50 元素数组更快但更节省空间的东西,类似于 EnumMap 给我的东西”基本上是在说“我想要一些不同于 50 元素数组的东西,类似于 50 个元素的数组。”这就是我要说的。 :) 我认为说“但大多数 EnumMap 的域较小,因此它们占用的空间更少”是不公平的,因为正是(通常)较小的域允许它们(通常)占用更少的空间,而这并不t 适用于您的情况。这并不是说 EnumMap 在解决时间与空间之间的权衡问题。

标签: java performance map hashmap


【解决方案1】:

数组应该是相当有效的,因为你的 Keys

您的地图(作为数组)的总大小是 4MB 还是 40MB 或其他大小有关系吗?您可以将 JVM 堆设置为大。

备选方案 2):

  • 编写您自己的基于哈希的地图类(不实现 collections.Map)。在单元格数组中使用“线性探针”相对简单——另一种技术是链表,它(再次)将与“直接数组”选项一样大。

【讨论】:

  • 也许只是我的 c 程序员偏执,在可能只需要 10 个空间的情况下分配 100 个空间似乎是一种浪费。特别是因为我有很多这样的地图,这使这个问题成倍增加。它仍然可能是少量内存......我将不得不考虑我自己的 Map 类。什么是线性探头方法?我不知道那个
  • 映射必须有比元素更多的单元,因为哈希码和它们映射到的单元不能保证唯一。 (你真的反对在这里使用数组,不是吗?)因此,具有相同“预期”单元格的不同元素将存储在下一个空单元格中。查找需要从指示的单元格沿哈希图进行线性扫描,扫描所有非空单元格(潜在的冲突),直到找到目标或到达一个空单元格。因此,HashMap 的大小必须始终大于“负载因子”所持有的# 个元素。 en.wikipedia.org/wiki/Linear_probing
  • 如果您想要性能,my comment above 应该表明数组将比您自己的自定义地图实现更快、更简单一个数量级。
【解决方案2】:

GNU Trove has primitive maps 会做你想做的事。但是,如果您不想勉强使用每个字节的内存,我会支持 Thomas 的建议,即只使用数组。

【讨论】:

  • 我总是忘记 Trove。 +1
  • 我喜欢这个。以前没有听说过 Trove,它看起来不错。这是一个相当大的图书馆,所以我必须看看我是否可以将我需要的地图从中分离出来。
  • 重点是,即使是(优化良好的)原始哈希映射的内存使用量也几乎与直接数组一样多。算了!执行成本会慢 5-10 倍左右。 坦率地说,此时您正在追求非生产性的努力。
  • @ThomasW:如果您说有效范围为 100 个键,有 许多 个单独的映射,并且其中许多只有 0-10 个条目,这可能是值得的在他们之中。但我同意你的观点,除非确实有令人信服的理由使用稀疏 Map,否则数组是更好的选择。
猜你喜欢
  • 1970-01-01
  • 2020-03-03
  • 1970-01-01
  • 2017-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-21
相关资源
最近更新 更多