我正在研究用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
:迭代器分配答案 0 :(得分:29)
要在不分配额外对象的情况下迭代数组,您可以使用以下方法之一。
for
- 环 for (e in arr) {
println(e)
}
forEach
扩展名 arr.forEach {
println(it)
}
forEachIndexed
扩展名,如果您需要知道每个元素的索引 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")
}