有没有一种方法可以迭代 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()
返回之前的某个时刻创建。
考虑到这一限制,可以采取三种合理的途径:
- 在
put()
上创建这个条目对象。 - 在
entrySet()
的第一次迭代中创建条目对象(但之后缓存它)。 - 在
entrySet()
的每次迭代中创建一个新的条目对象。
内置 EnumMap
选择选项 3 的可能原因是它最容易实现,而且如果您不需要遍历条目,它是最经济的解决方案。缺点是如果您需要多次迭代,您创建的对象比任何其他解决方案都多。
选项 1 实现起来同样简单,但每次向 map 添加条目时都会产生明显的开销,即使您从未打算访问它也是如此。
最后,选项 2 涉及稍微复杂的代码,以及在迭代和添加更多元素之间交替时的一些边缘情况,但它为您提供理论上最好的内存配置文件。
如果多次迭代的内存开销被证明是您的应用程序中的一个问题,您可以轻松地实现选项 2,但我怀疑在大多数情况下差异是否会很明显。
P.s.:如果您愿意偏离惯用的解决方案并进入稍微疯狂的领域,您可以为所有条目重复使用相同的 Map.Entry
实例。这显然与我们对 Map.Entry
的期望相矛盾,但它为您提供了最小的内存分配开销,并且您可以在简单的迭代场景中摆脱它。是否最终得到更快的最终产品是任何人的猜测,您需要对其进行衡量。
关于java - 迭代 EnumMap 不会导致每次迭代都创建新对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41703256/