【问题标题】:No definite answer: Which Java Map is the cheapest?没有明确的答案:哪个 Java Map 最便宜?
【发布时间】:2014-12-28 09:07:53
【问题描述】:

以前可能有人问过,但我一次又一次地遇到这种情况,我想存储非常少量的属性,我绝对肯定永远不会超过 20 个键。一开始就使用 HashMap 似乎完全浪费了 CPU 和内存,而且为每个键查找计算高级哈希值的性能也很差。如果只有

有关于过早优化的讨论,但我不完全同意这里。我主要使用 Android,任何额外的 CPU/内存都会为其他东西选择更多汁液。这里不一定要谈消费市场。此外,这里的用例定义非常明确,变化不大;用 HashMap 替换一个非常便宜的映射是微不足道的,以防万一(永远不会发生的事情)突然有大量的新键。

所以,我的问题是;哪个是我可以在 Java 中使用的最便宜、最基本的 Map?

【问题讨论】:

  • 只使用数组怎么样?
  • @hatchet 它不会比HashMap 更有效(也就是说,它包含一个数组)并且不可读,特别是如果数组没有完全填充
  • @Dici - 5 个元素?好像把你的车开到车道上 30 英尺去取你​​的邮件。如果 OP 既担心空间成本又担心时间成本,那么数组将赢得空间,并且在时间上无法区分,但也很可能更快。
  • @hatchet 他可以玩初始容量和负载系数。与他手动使用数组时必须编写的代码的丑陋相比,这么小的开销不算什么
  • 这可能毫无意义,因为说实话,我很难相信它在你的应用程序中真的很重要。如果没关系,可读性/可维护性获胜。我同意@Dici。

标签: java performance map key


【解决方案1】:

对于你的第一段:不!不会有巨大的内存开销,因为据我所知,HashMap 用 16 个桶初始化,然后每次都将其大小翻倍它会重新散列,因此在最坏的情况下,您的地图会超过 12 个桶,所以这没什么大不了的。

关于查找时间,它是恒定的,相当于访问数组元素的时间,这总是比循环遍历O(n)元素(即使n HashMap 的唯一背景是它是未排序的,但就我而言,当我对顺序没有特别要求时,我认为它是 Java 中默认的 Map 实现。

总结:使用HashMap

【讨论】:

  • 我同意查找时间是恒定的,但是计算哈希值如何等同于遍历数组?
  • 这取决于你的哈希函数,但一般不会那么昂贵。我的观点是你不应该阻止你使用高级数据结构进行花生优化。代码可读性和功能性是您的首要任务。另外,在遍历您的数组时,您必须调用equals(多次),它的运行时间可以与hashCode(您只调用一次)相当。
  • 好的答案!所以我可以安全地继续我的实践,始终使用 HashMaps。很高兴知道。
  • 如果您不关心订购,可以。对于HashMap 的优化使用,了解负载因子和初始容量如何影响重新散列的次数(这在使用HashMap 时确实需要时间)。但是老实说,我几乎从不关心这个并使用默认构造函数。很高兴知道您需要优化代码以达到性能目标的那一天
  • 不想质疑结论,但是当 n 仅为 20 时,您不能使用 O 表示法来争论速度。当您比较 O(1) 与 O(N) 时,您是在比较 O( 1 xa) 与 O(20 xb) 不知道每一边的常数因子 a 和 b 到底有多大。
【解决方案2】:

如果您担心键上的 hashCode() 计算时间,请考虑缓存计算值,例如 java.lang.String 所做的那样。请参阅how caching hashcode works in Java as suggested by Joshua Bloch in effective java? 相关问题。

【讨论】:

    【解决方案3】:

    警告:我建议您认真注意过早优化。对于大多数应用程序中的大多数程序员,我严重怀疑您是否需要担心Map 的性能。更重要的是考虑并发性、迭代顺序和空值的需求。不过既然你问了,这里就是我的具体回答。

    EnumMap

    如果您的密钥是enums,那么您最快的Map 实现将是EnumMap

    基于表示枚举对象域的位图,EnumMap 的执行速度非常快,同时使用的内存非常少。

    IdentityHashMap

    如果你真的很在意性能,那么考虑使用IdentityHashMap

    Map 的这个实现使用引用相等而不是对象相等。虽然仍然涉及哈希值,但它是对象在内存中地址的哈希值(可以这么说,我们在 Java 中没有直接的内存访问)。因此,完全避免了对每个关键对象自己的 hashCode 方法的可能冗长的调用。所以性能可能比HashMap 更好。您将看到基本操作(getput)的恒定时间性能。

    仔细研究文档,看看你是否想走这条路。请注意关于 linear-probechaining 的讨论以获得更好的性能。请注意,此类部分违反了Map 合同,该合同要求在比较对象时使用equals 方法。而且这个map不提供并发。


    这是我为帮助比较与 Java 11 捆绑的各种 Map 实现而制作的表格。

    【讨论】:

      猜你喜欢
      • 2011-08-28
      • 1970-01-01
      • 2015-06-01
      • 2014-06-26
      • 2016-09-03
      • 1970-01-01
      • 2013-12-06
      • 1970-01-01
      相关资源
      最近更新 更多