玖叶教程网

前端编程开发入门

Kotlin 技巧:使用序列提高大数据处理性能

假设有一个数字列表,你想取所有奇数的平方根,然后找到第一个大于 100 的数字。一种方法是过滤所有奇数,然后遍历结果,对所有数字进行平方运算,然后再次遍历列表找到第一个大于 1000 的数字:

val numbers = (1..20) // 创建一个从1到20的列表
val oddSquared = numbers
                   .filter { it % 2 != 0 } // 过滤出奇数
                   .map { it * it } // 将过滤得到的数字平方
                   .first { it > 10 } // 找到第一个大于10的数字

这里的问题是,每一步都在整个列表上操作,或者在前一步的结果上操作。这就创建了使用额外内存的列表。同时,它在最后答案不需要的部分列表上工作,从而浪费了资源。因此,它不仅效益低下,而且比必要的工作更多,通过在每一步都制作新的列表,使用了更多的内存。

更有效的方式是将我们的列表转换成序列。使用序列,操作不会立即执行。相反,将一次处理一个元素,构成一个操作链,并且一旦满足最后的条件,处理就会停止:

val numbers = (1..20) // 创建一个从1到20的列表
val oddSquared = numbers.asSequence() // 转换为序列
                   .filter { it % 2 != 0 }// 过滤出奇数
                   .map { it * it } // 将过滤得到的数字平方
                   .first { it > 10 } // 找到第一个大于10的数字

通过使用序列,当定义过滤奇数的操作或定义平方数字的映射操作时,不会有任何计算发生。评估只有在结果实际需要时才开始处理,这发生在我们调用 first()时。

序列一次处理一个元素:它取第一个元素(1),检查它是否是奇数(是),将它平方(1),并检查结果是否大于 10(不是)。这个过程继续到下一个元素并重复。当它到达 5 时,通过奇数检查,平方得到 25,由于 25 大于 10,迭代停止。

现在,设置一个实验。使用一个数字列表,并同时进行过滤和映射操作。为了观察行为,我们将在操作中添加打印语句。

首先,使用列表:

fun main() {
    val numbers = (1..20)
    println("Starting eager evaluation...")

    val eagerResult = numbers
        .filter {
            println("Filtering $it")
            it % 2 != 0 // odd numbers
        }
        .map {
            println("Mapping $it")
            it * it // squaring
        }
        .first {
            println("Evaluating $it")
            it > 10
        }

    println("Eager result: $eagerResult")
}

这段代码将打印过滤和映射每个数字时的消息,显示所有操作都是立即执行的,且对所有元素执行。

现在,使用序列演示:

fun main() {
    val numbers = (1..20).asSequence()
    println("Starting lazy evaluation...")

    val lazyResult = numbers
        .filter {
            println("Filtering $it")
            it % 2 != 0 // odd numbers
        }
        .map {
            println("Mapping $it")
            it * it // squaring
        }
        .first {
            println("Evaluating $it")
            it > 10
        }

    println("Eager result: $lazyResult")
}

在这个序列示例中,过滤和映射操作中的 print 语句将帮助解释每个元素何时以及如何被处理。

通过使用序列的懒赋值,Kotlin 允许更有效的数据处理,尤其是在可能无需处理整个集合以得到结果的情况下。

然而,请记住,虽然asSequence可以提高性能,但并非所有集合处理场景的万能良药。对于小型集合或简单操作,转换为序列和从序列转换的开销可能会抵消。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言