有没有办法迭代EnumMap,它不会导致每次迭代创建一个新对象? entryset的迭代器每次都返回一个新的Entry。我能看到的唯一方法是
WpfApplication.App
为了澄清这一点,特别是EnumMap在其EntrySet上具有以下迭代器实现
for(K k: map.keySet())
foo(k, map.get(k));
答案 0 :(得分:2)
首先,从您所说的内容来看,您似乎希望迭代器返回两个对象的元组。
在Java中,唯一的方法是将它们包装在另一个对象中。 (在编写本文时,就是这样。)因此迭代器必须返回除键和值之外的对象。必须在调用next()
之前的某个时刻创建该对象。
考虑到这种限制,有三条合理的路径可供选择:
put()
上创建此条目对象。entrySet()
的第一次迭代中创建条目对象(但之后将其缓存)。entrySet()
的每次迭代中创建一个新的条目对象。内置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) -> {...});