迭代EnumMap,它不会导致每次迭代创建一个新对象

时间:2017-01-17 17:20:13

标签: java keyset enum-map

有没有办法迭代EnumMap,它不会导致每次迭代创建一个新对象? entryset的迭代器每次都返回一个新的Entry。我能看到的唯一方法是

WpfApplication.App

为了澄清这一点,特别是EnumMap在其EntrySet上具有以下迭代器实现

for(K k: map.keySet()) 
    foo(k, map.get(k));

3 个答案:

答案 0 :(得分:2)

首先,从您所说的内容来看,您似乎希望迭代器返回两个对象的元组。

在Java中,唯一的方法是将它们包装在另一个对象中。 (在编写本文时,就是这样。)因此迭代器必须返回除键和值之外的对象。必须在调用next()之前的某个时刻创建该对象。

考虑到这种限制,有三条合理的路径可供选择:

  1. put()上创建此条目对象。
  2. entrySet()的第一次迭代中创建条目对象(但之后将其缓存)。
  3. entrySet()的每次迭代中创建一个新的条目对象。
  4. 内置EnumMap用于选项3,原因可能是最简单的实现,如果您不需要遍历条目,这是最经济的解决方案。缺点是如果您需要多次迭代,则创建的对象比任何其他解决方案都多。

    选项1实现起来非常简单,但每次向地图添加条目时都会有明显的开销,即使您从未打算访问它。

    最后,选项2涉及稍微多一点的代码复杂性,以及在迭代和添加更多元素之间交替时的几个边缘情况,但它在理论上为您提供了最佳的内存配置文件。

    如果多次迭代的内存开销被证明是您应用程序中的一个问题,那么您可以轻松实现选项2,但我怀疑在大多数情况下差异是显而易见的。

    P.s。:如果您愿意偏离惯用的解决方案并进入略微疯狂的领域,您可以为所有条目重复使用相同的Map.Entry实例。这显然与我们对Map.Entry的期望相矛盾,但它为您提供了最小的内存分配开销,您可以在简单的迭代场景中使用它。无论你最终得到一个更快的最终产品是任何人的猜测,你需要测量它。

答案 1 :(得分:1)

我反思地怀疑这种关注对象创造的合法性。但是如果避免对象创建真的很重要,那么你可以维护自己的枚举常量数组并为每个常量测试map.contains(...)。您必须对此进行测试,以了解性能如何比较。

答案 2 :(得分:0)

首先,您的代码每次都创建一个对象。它只会对现有对象获得引用

是的,还有更好的方法:

for (Map.Entry<K, V> entry : map.entrySet()) {
    // use entry.getKey() and entry.getValue()
}

或Java 8版本:

map.forEach((k, v) -> {...});