java - Map.of 与 EnumMap 用于具有枚举键的不可变映射

标签 java performance dictionary enums time-complexity

EnumMap使用映射的所有键都来自同一 enum 的限制来获得性能优势:

Enum maps are represented internally as arrays. This representation is extremely compact and efficient.

在这种情况下,键和值存储在单独的数组中,并且值按序号排序。迭代是通过内部 EnumMapIterator 类完成的。

由各种 Map.of 创建的不可变映射方法使用映射不会在结构上发生变化的限制来获得性能优势。如果映射的大小不是 0 或 1,则它使用 MapN 内部类,该内部类也将其条目存储在数组中。在这种情况下,该值存储在其键之后的 1 个索引处。迭代是通过内部 MapNIterator 完成的。

对于大小为 2 或更大的 enum 键的不可变映射,它满足上述两个要求,哪个映射性能更好? (标准可以是 containsKeycontainsValueget 的空间效率、时间效率以及 entrySet 的迭代效率, keySetvalue。)

最佳答案

which map gives better space efficiency, and time efficiency for its operations and iteration: containsKey, containsValue, get, entrySet, keySet and values?

你提出了 1 + 6(或 2 * 6,取决于如何理解)的问题,这有点太多了。如果你想要一个明确的答案,你必须专注于一件事并分析它(除非你发现一个非常有趣的问题,否则没有人会为你做这件事)。

<小时/>

EnumMap 的空间效率必须更高。无需存储键,因为可以使用共享枚举数组。不需要a holes-containing hash lookup array .

可能会有异常(exception),例如基于巨大枚举的小 map 。

<小时/>

最重要的操作是get。使用EnumMapit involves no lookup ,只是一个trivial class comparison和数组访问。对于 Map.of(...),有一个 loop ,对于枚举,通常在第一次迭代后终止,因为 Enum.hashCodeIMHO stupid ,但通常分布良好。

由于 containsKey 基于相同的查找,所以很清楚。

我怀疑,我曾经使用过 containsValue,但它并没有做任何比线性搜索更智能的事情。由于存在漏洞(需要简单的空测试,但会导致分支错误预测),我预计 EnumMap 会取得微小的胜利。

剩下的三个操作不值得查找,因为它们返回一个不包含数据的集合,只是指向 map ,即恒定时间操作。例如,map.keySet().contains(x) 只是委托(delegate)给 map.containsKey()

迭代的效率会是一个更有趣的问题,但你没有问。

关于java - Map.of 与 EnumMap 用于具有枚举键的不可变映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52281364/

相关文章:

PHP/MySQL(i) use_result、store_result 和 MyISAM 表锁

c++ - C++ 中的多重映射

ios - 在 iOS 上带路线的离线 map

java - ScheduledThreadPoolExecutor,如何停止可运行类JAVA

java - 如何从 JSONObject 接收数据到简单数组

java - 值没有插入到 SQLite 数据库

python - 更新Python字典而不覆盖子字典的通用方法

java - 使用 CDI 在运行时创建和连接相关实例

mysql - 在非常慢的服务器 2 上替代内连接

c# - 我可以减少 WPF 应用程序中手写笔/触摸输入的开销吗?