没有额外对象分配的数组/列表迭代

时间:2016-06-03 08:01:45

标签: kotlin

我正在研究用Kotlin编写的游戏,并正在研究改善GC流失。流失的主要来源之一是主游戏/渲染循环中调用的for循环,导致迭代器的分配。

转到文档,我发现了这一段:

  

数组上的for循环被编译为基于索引的循环,该循环不会创建迭代器对象。

     

如果要迭代数组或带索引的列表,可以这样做:

for (i in array.indices)
  print(array[i])
  

请注意,这种“范围内的迭代”会被编译为最佳实现,而不会创建额外的对象。

https://kotlinlang.org/docs/reference/control-flow.html#for-loops

这是真的吗?为了验证,我采用了这个简单的Kotlin程序并检查了生成的字节代码:

fun main(args: Array<String>) {
    val arr = arrayOf(1, 2, 3)
    for (i in arr.indices) {
        println(arr[i])
    }
}

根据上面的引用,这不应该导致分配任何对象,而是编译成一个很好的旧Java-5前样式for循环。但是,我得到的是:

      41: aload_1
      42: checkcast     #23                 // class "[Ljava/lang/Object;"
      45: invokestatic  #31                 // Method kotlin/collections/ArraysKt.getIndices:([Ljava/lang/Object;)Lkotlin/ranges/IntRange;
      48: dup
      49: invokevirtual #37                 // Method kotlin/ranges/IntRange.getFirst:()I
      52: istore_2
      53: invokevirtual #40                 // Method kotlin/ranges/IntRange.getLast:()I
      56: istore_3
      57: iload_2
      58: iload_3
      59: if_icmpgt     93

这看起来好像调用了一个名为getIndices的方法,该方法分配一个临时的IntRange对象来备份此循环中的边界检查。这是一个&#34;最佳实施&#34;用&#34;没有创建额外的对象&#34;,或者我错过了什么?

更新 因此,经过多一点的考虑并查看答案之后,Kotlin 1.0.2似乎也是如此:

阵列

  • for (i in array.indices):范围分配
  • for (i in 0..array.size):没有分配
  • for (el in array):没有分配
  • array.forEach:没有分配

类别:

  • for (i in coll.indices)范围分配
  • for (i in 0..coll.size):没有分配
  • for (el in coll):迭代器分配
  • coll.forEach:迭代器分配

3 个答案:

答案 0 :(得分:29)

要在不分配额外对象的情况下迭代数组,您可以使用以下方法之一。

  1. for - 环
  2.     for (e in arr) {
            println(e)
        }
    
    1. forEach扩展名
    2.     arr.forEach {
              println(it)
          }
      
      1. forEachIndexed扩展名,如果您需要知道每个元素的索引
      2.     arr.forEachIndexed { index, e ->
                println("$e at $index")
            }
        

答案 1 :(得分:14)

据我所知,定义for循环的唯一无分配方法是

for (i in 0..count - 1)

所有其他表单都会导致Range分配或Iterator分配。不幸的是,您甚至无法定义有效的反向for循环。

答案 2 :(得分:0)

这里是准备列表并使用索引和值进行迭代的示例。

val list = arrayListOf("1", "11", "111")
for ((index, value) in list.withIndex()) {
   println("$index: $value")
}

输出:

0:1

1:11

2:111

此外,以下代码的工作原理相似,

val simplearray = arrayOf(1, 2, 3, 4, 5)
for ((index, value) in simplearray.withIndex()) {
    println("$index: $value")
}