Kotlin 中 fold() 和 reduce() 的区别

David Mbochi Njonge 2023年1月30日
  1. Kotlin fold() 方法的作用
  2. Kotlin reduce() 方法实战
  3. 结论
Kotlin 中 fold() 和 reduce() 的区别

fold()reduce() 方法是 Iterable 接口的扩展函数。这些方法使用元素列表并将它们转换为单个元素。

由于 Collection 接口实现了 Iterable 接口,因此我们可以将这些方法用于作为 Collection 类的子类型的任何类或接口。

在本教程中,我们将通过了解 fold()reduce() 方法的工作原理并为每种情况提供示例来了解它们之间的区别。

Kotlin fold() 方法的作用

转到 IntelliJ 并选择 File > New > Project 创建一个新项目。将项目名称输入为 kotlinFoldAndReduce,或任何首选名称。在 Language 部分选择 Kotlin,在 Build System 部分选择 Intellij。按创建按钮创建项目。

创建项目后,为 fold() 方法创建文件夹结构 com/fold,为 reduce() 方法创建 com/reduce

fold 文件夹下创建一个名为 Main.kt 的新文件,并将以下代码复制并粘贴到该文件中。

package com.fold

class Product(private val name: String,
               private val price: Int){

    fun getName(): String{
        return this.name;
    }

    fun getPrice(): Int{
        return this.price
    }
}

val  products: List<Product> = listOf(
    Product("Hp laptop",200),
    Product("Java book",320),
    Product("Iphone 13",150)
)

fun main() {
    println(products.fold(0) { total, employee ->
       total+employee.getPrice()
    });
}

我们在这段代码中创建的 listOf() 辅助方法将返回 Product 元素的列表,从返回的列表中,我们可以调用 fold() 方法。

当我们调用 fold() 方法时,我们必须提供将用作计算累加器的初始值。请注意,如果返回的集合为空,则 fold() 方法会返回我们提供的初始值。

运行代码并验证它是否输出列表中所有产品元素的总价格,如下所示。

输出:

670

fold() 方法也可用于检查至少大于或小于初始值的值。下面的示例测试列表中的所有 product 元素以返回至少大于 300 的 product 价格,因此我们将 300 设置为 fold() 函数的初始值。

在将此示例复制并粘贴到文件中之前,请确保在 main 方法中注释掉前面的示例。

fun main() {
    println(products.fold(300) { expensiveProduct, product ->
        if (product.getPrice() > expensiveProduct)
            product.getPrice() else expensiveProduct
    });
}

运行代码以验证它是否输出以下值:列表中所有 product 元素的最高价格。

输出:

320

Kotlin reduce() 方法实战

reduce 文件夹下创建一个 Main.kt 文件,并将以下代码复制并粘贴到该文件中。

package com.reduce

val list: List<Int> = listOf(20,40,60)

fun main() {
    println(list.reduce { sum, value ->
        sum + value
    });
}

由于 reduce() 方法没有初始值,它使用列表的第一个元素作为初始值。在本例中,值 20 是第一个累加器值,使用 40 的计算返回下一个累加器值。

运行代码并确保它输出以下结果。

输出:

120

在前面的示例中,我们了解到如果列表为空,则返回提供的初始值。reduce() 方法抛出 UnsupportedOperationExceptionRuntimeException,以防列表为空。

为了防止 reduce() 方法抛出 RuntimeException,我们可以在进行任何计算之前检查列表是否为空。如果 int 类型列表为空,则以下代码返回值 0

对上一个示例进行注释,并将此示例复制并粘贴到注释后的文件中。

package com.reduce

val list: List<Int> = listOf()

fun main() {
    val data = if (list.isEmpty()) 0
    else list.reduce { sum, value ->
        sum + value
    }
    println(data);
}

运行代码并注意记录到控制台的值是 0,因为我们创建的列表是空的。

输出:

0

结论

在本教程中,我们学习了如何区分 fold()reduce() 扩展函数。我们还介绍了这两种方法如何处理列表为空的情况以避免可能引发的异常。

David Mbochi Njonge avatar David Mbochi Njonge avatar

David is a back end developer with a major in computer science. He loves to solve problems using technology, learning new things, and making new friends. David is currently a technical writer who enjoys making hard concepts easier for other developers to understand and his work has been published on multiple sites.

LinkedIn GitHub