java - 迭代 EnumMap 不会导致每次迭代都创建新对象

标签 java keyset enum-map

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

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

澄清这是专门关于 EnumMap 的,它在其 EntrySet 上有以下迭代器实现

 public Map.Entry<K,V> next() {
        if (!hasNext())
            throw new NoSuchElementException();
        lastReturnedEntry = new Entry(index++);
        return lastReturnedEntry;
    }

最佳答案

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

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

考虑到这一限制,可以采取三种合理的途径:

  1. put() 上创建这个条目对象。
  2. entrySet() 的第一次迭代中创建条目对象(但之后缓存它)。
  3. entrySet() 的每次迭代中创建一个新的条目对象。

内置 EnumMap 选择选项 3 的可能原因是它最容易实现,而且如果您不需要遍历条目,它是最经济的解决方案。缺点是如果您需要多次迭代,您创建的对象比任何其他解决方案都多。

选项 1 实现起来同样简单,但每次向 map 添加条目时都会产生明显的开销,即使您从未打算访问它也是如此。

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

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

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

关于java - 迭代 EnumMap 不会导致每次迭代都创建新对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41703256/

相关文章:

java - Cloud PubSub Java 并行致谢

Java编译器错误: "cannot find symbol constructor .."?

java - 如何在java中的sql查询中使用map.KeySet()

java - 为什么Java 6重写SortedMap中的keySet()、entrySet()和values()接口(interface)

java - 代码说明: Enum and Rendering

java - 带有 LuaJava 的 EnumMap(尝试调用 nil 值)

Java:valueOf 与 copyValueOf

java - Spring 计划任务未在 Windows 7 上执行

java - 避免 map.get(key) 方法

java - 为什么 EnumMap 内部数组是 transient 的