首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >数组/列表迭代,不需要额外的对象分配

数组/列表迭代,不需要额外的对象分配
EN

Stack Overflow用户
提问于 2016-06-03 08:01:45
回答 3查看 46.9K关注 0票数 48

我正在写一个用Kotlin写的游戏,并且正在研究如何提高GC的效率。搅拌的主要来源之一是主游戏/渲染循环中调用的for-循环,这会导致迭代器的分配。

关于文件,我发现这一段:

数组上的for循环编译为不创建迭代器对象的基于索引的循环。 如果您想用索引迭代数组或列表,可以这样做:

代码语言:javascript
复制
for (i in array.indices)
  print(array[i])

请注意,这个“通过范围的迭代”被编译成最佳实现,没有创建额外的对象。

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

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

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

根据上面的引号,这不应该导致分配任何对象,而是被编译成一个很好的以前Java-5风格的for-循环。然而,我得到的是:

代码语言:javascript
复制
      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对象来备份这个循环中的边界检查。这是一个“没有额外创建的对象”的“最佳实现”,还是我遗漏了什么?

更新:所以,在多玩了一会儿并查看了答案之后,对于Kotlin 1.0.2,下面的内容似乎是正确的:

数组:

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

Collections:

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

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-06-03 08:24:53

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

代码语言:javascript
复制
for (i in 0..count - 1)

所有其他形式都会导致Range分配或Iterator分配。不幸的是,您甚至不能定义一个有效的反向for循环。

票数 22
EN

Stack Overflow用户

发布于 2016-06-03 16:19:39

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

  1. for-loop
代码语言:javascript
复制
    for (e in arr) {
        println(e)
    }
  1. forEach扩展
代码语言:javascript
复制
    arr.forEach {
        println(it)
    }
  1. forEachIndexed扩展,如果您需要知道每个元素的索引
代码语言:javascript
复制
    arr.forEachIndexed { index, e ->
        println("$e at $index")
    }
票数 49
EN

Stack Overflow用户

发布于 2020-02-09 07:45:17

下面是一个准备列表并使用索引和值进行迭代的示例。

代码语言:javascript
复制
val list = arrayListOf("1", "11", "111")
for ((index, value) in list.withIndex()) {
   println("$index: $value")
}

输出:

0:1

1:11

2:111

另外,下面的代码也是类似的,

代码语言:javascript
复制
val simplearray = arrayOf(1, 2, 3, 4, 5)
for ((index, value) in simplearray.withIndex()) {
    println("$index: $value")
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37609071

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档