Kotlin:有什么方法可以将其作为序列进行迭代吗?

时间:2019-05-04 17:00:23

标签: kotlin sequence

我正在做一个图像过滤器,我已经做完了,但是我读过对于大型集合,使用序列进行迭代会更好,并且由于是8k图像,我想我会获得一些性能因为它是使用Sequence<IntArray>而不是Array<IntArray>甚至是Sequence<Sequence<Int>>进行的延迟初始化。我不知道这是否可行,我很困惑,想为我学习这种新的范例,而且我很难找到更容易理解这一概念的用法的材料。

这是一个尝试,但是很混乱,我对如何进行此操作并不太了解,即使我也应该将“ newImage”用作Sequence。

val myPredicate = { array : IntArray -> !array.first() /*???*/ && !array.last() }
image.asSequence().forEach { array ->
    array.filter(myPredicate ) // ???
}

这是要转换的功能代码:

fun chunker(image : Array<IntArray>) : Array<IntArray> {
    val arrayRowSize = image.size
    val arrayColSize = image[0].size
    val newImage : Array<IntArray> by lazy {
        Array(arrayRowSize) { IntArray(arrayColSize) }
    }

    var kernel = IntArray(9)
    // to translate to a Sequence those two for loops
    for (row in 1 .. arrayRowSize - 2) {
        for (col in 1 .. arrayColSize - 2) {
            kernel = changer(row, col, kernel, image)
            newImage[row][col] = kernel[4]
        }
    }
    return newImage
}

1 个答案:

答案 0 :(得分:0)

  

我已经读到,对于大型集合,最好使用序列进行迭代

您可能已经读到的是,给定myCollection.filter(...).map(...).first(...)之类的功能管道,可以通过使用Sequence来提高性能,主要有以下两个原因:

  1. 如果不需要,序列将不会处理所有元素(first(),并且结尾可能使序列在看到所有元素之前终止)
  2. 与常规集合不同,该序列不会为每个管道步骤(例如过滤器或地图)创建中间集合

在您的情况下,您甚至没有功能操作的流水线,也没有创建中间集合,因为您直接创建并填充结果。此外,您不能提早终止,因为您想无论如何都要处理所有像素,因此Sequence可能是适当的,但在此处不一定会提高性能。

如果您正在针对JVM编译此Kotlin代码,那么至少可以做一件事来提高性能:

使用带有特殊索引的1D数组代替使用2D数组。更具体地说,您可以编写newImage[row][col]而不是newImage[row * width + col]。 这样可以避免重复存储引用和benefit from cache locality,因为您要逐行进行迭代。