之前可能有人问过,但我一次又一次地遇到这种情况,我希望存储一个非常小的属性,我绝对肯定永远不会超过20键。使用带有所有开销的HashMap似乎完全浪费了CPU和内存,但是为每个键查找计算高级哈希值的性能也很差。如果只有< 20键(大多数时候可能更像是5个键)。我绝对肯定计算哈希值所花费的时间比迭代和比较的时间要多一百倍......不是吗?
有关于过早优化的讨论,但我并不完全赞同。我主要在Android上,任何额外的CPU /内存都会选择更多的其他东西。不一定在这里讨论消费市场。这里的用例非常明确,而且变化不大;如果用一个HashMap替换一个非常便宜的地图(一些永远不会发生的事情)会突然出现非常大量的新密钥,这将是微不足道的。
所以,我的问题是;这是我在Java中可以使用的最便宜,最基本的Map?
答案 0 :(得分:1)
至于你的所有第一段:不!因为据我所知,HashMap
初始化了16个桶然后加倍,所以不会引起巨大的内存开销它的大小每次重新出现,所以在最糟糕的情况下,你的地图会有12个超级桶,所以这没什么大不了的。
关于查找时间,它是恒定的并且等同于访问数组元素的时间,这总是优于循环O(n)
元素(即使n <20)。 HashMap
的唯一背景是它没有排序,但就我而言,我认为它是Java中的默认Map
实现,当我对订单没有特别要求时。
总结:使用HashMap
!
答案 1 :(得分:0)
如果您担心密钥的hashCode()
计算时间,请考虑缓存计算值,例如java.lang.String
。请参阅how caching hashcode works in Java as suggested by Joshua Bloch in effective java?有关此问题的问题。
答案 2 :(得分:0)
注意事项:我建议您在过早优化时要格外小心。对于大多数应用中的大多数程序员而言,我严重怀疑您是否需要担心Map
的性能。更重要的是考虑并发,迭代顺序和空值的需求。但是,既然你问了,这就是我的具体答案。
EnumMap
如果您的密钥是enums,那么最快的Map
实现将是EnumMap
。
基于表示枚举对象域的位图,EnumMap
的执行速度非常快,而占用的内存却很少。
IdentityHashMap
如果您真的非常关心性能,请考虑使用IdentityHashMap
。
此Map
的实现使用引用相等而不是对象相等。尽管仍然涉及哈希值,但它是内存中对象地址的哈希值(可以这么说,在Java中我们没有直接的内存访问权限)。因此,完全避免了对每个关键对象自己的hashCode
方法的可能冗长的调用。因此,性能可能比HashMap
更好。您将看到基本操作(get
和put
)的恒定时间性能。
仔细研究文档,以了解是否要采用这种方法。请注意有关 linear-probe 与 chaining 的讨论,以获得更好的性能。请注意,该类部分违反了Map
协定,该协定要求比较对象时必须使用equals
方法。而且此映射不提供并发性。
这是我制作的一张表格,用于比较Java 11捆绑的各种Map
实现。