Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 迭代HashMap的值,而不创建任何要进行垃圾收集的新对象_Java_Hashmap_Iteration - Fatal编程技术网

Java 迭代HashMap的值,而不创建任何要进行垃圾收集的新对象

Java 迭代HashMap的值,而不创建任何要进行垃圾收集的新对象,java,hashmap,iteration,Java,Hashmap,Iteration,我试图在Java中迭代HashMap的值,而不创建任何需要垃圾收集的新对象。使用增强的for循环很容易迭代值,如下所示: for (Value v : myMap.values()) { .... } 但这将在幕后创建一个迭代器对象(我想是吧?) 我想到的最好的代码是: Object[] values = myMap.values.toArray(); ...standard "int i" for loop on the array Object[] values = myMa

我试图在Java中迭代HashMap的值,而不创建任何需要垃圾收集的新对象。使用增强的for循环很容易迭代值,如下所示:

for (Value v : myMap.values()) {
    ....
}
但这将在幕后创建一个迭代器对象(我想是吧?)

我想到的最好的代码是:

Object[] values = myMap.values.toArray();
...standard "int i" for loop on the array
  Object[] values = myMap.values.toArray();
  ...standard "int i" for loop on the array
但老实说,我不确定GC将如何处理这个数组

有没有一种完美的方法可以做到这一点,或者有没有一种方法可以用一个可重用的对象做到这一点

编辑:这是针对Android游戏的,有很多这样的循环在创建对象并影响性能


编辑#2:对于那些持怀疑态度的人来说,我重构了最常见的增强For循环的一部分,主要是在ArrayList上,这对基于jvisualvm堆分析的内存使用产生了重大影响。当然,部分原因可能是因为我有太多的ArrayList,或者在不需要的时候循环使用它们。

for each循环是目前为止最好的选择:它既高效又可读

老实说,在避免创建迭代器时,您不会注意到任何变化。迭代器是专门为迭代而设计的,因此它在这样做时是高效和优化的。创建数组是最糟糕的选择:它为已经处于完全可移植数据结构中的对象分配内存

关于您的编辑:您确定这是因为迭代器吗?你真的对它进行了微基准测试吗?我敢肯定,在这个循环中,有一些东西比简单地创建一个非常轻的对象要花费更多的时间。在使代码复杂化之前,尝试弄清楚这是什么,并优化真正重要的内容

但这将在幕后创建一个迭代器对象(我想是吧?)

是的,会的

我想到的最好的代码是:

Object[] values = myMap.values.toArray();
...standard "int i" for loop on the array
  Object[] values = myMap.values.toArray();
  ...standard "int i" for loop on the array
但老实说,我不确定GC将如何处理这个数组

事实上,这将比显式或隐式使用
迭代器更糟糕:

  • toArray()
    方法分配一个新数组并将值集元素复制到其中
  • 调用
    values()
    可以实例化
    Set
    对象
  • toArray()
    的调用在内部调用值集对象上的
    iterator()
    ,该对象将创建一个新的
    iterator
    实例
因此,您正在分配一个
迭代器
,以及一个临时数组和(可能)一个
集合
对象



我分析了堆,最大的对象集是
ArrayList$Itr
(与此
HashMap
示例无关,但我目前正在将所有增强for循环重写为标准for循环)


正如你所指出的,这是另一种情况。但我还是觉得你找错地方了。如果您使用的是最新的HotSpot JVM,那么分配和垃圾收集短期对象(即那些没有终身使用权的对象)的成本非常小。除非您有特定的理由降低对象分配率,否则您的所有工作在实际可测量的性能改进方面可能收效甚微。

为什么不创建一个对象?我认为创建迭代器的开销不值得创建一个(可能很奇怪的)解决方案。但如果有充分的理由的话,我很想听听你为什么在乎?创建迭代器和垃圾收集非常快。不要优化不需要优化的东西。为什么必须没有临时对象?您见过使用“快速”迭代器的
fastutil
集合吗?我最近发现了这些。它们用于高效地迭代映射条目(提供只读接口,但impl是读/写的)。如果您有一个需要频繁映射项迭代的关键部分,它可能会有所帮助。我分析了堆,最大的对象集是ArrayList$Itr(与此HashMap示例无关,但我目前正在将所有增强for循环重写为标准for循环)。感谢这些信息,它为我清除了一些问题。一件事是,因为这是一款Android游戏,它在Dalvik虚拟机上,而不是HotSpot上。我知道Davlik虚拟机的GC不如HotSpot的好。但我仍然只会在应用程序/游戏遇到GC暂停时优化迭代器的使用。