Kotlin中的Fold与Reduce:何时使用什么?全面解析

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Kotlin中的Fold或Reduce:初学者的永恒问题

\n\n

如果你使用Kotlin编程至少一周,你肯定已经遇到过fold和reduce函数。乍一看,它们做的是同一件事:遍历集合并累积结果。但魔鬼,一如既往,藏在细节中。错误的选择可能导致bug、异常,或者仅仅是不美观的代码。

\n\n

在本文中,我们将分析Kotlin中fold和reduce的区别,通过真实项目中的实例来观察,并永远记住何时使用哪个函数。开始吧!

\n\n

什么是fold和reduce?基本理解

\n\n

这两个函数都属于集合的终端操作。它们获取所有元素并将它们折叠成一个值。想象一下,你有一摞煎饼,而你想得到一个巨大的汉堡。fold和reduce是两种不同的折叠技巧。

\n\n

Reduce:极简主义方法

\n\n

reduce函数使用集合的第一个元素作为累加器的初始值。这意味着它无法处理空集合——会抛出UnsupportedOperationException异常。

\n\n
val numbers = listOf(1, 2, 3, 4, 5)\nval sum = numbers.reduce { acc, i -> acc + i }\nprintln(sum) // 15
\n\n

这里,acc初始等于1(第一个元素),然后依次加上2、3,以此类推。简单而优雅,但有一个细微之处。

\n\n

Fold:对初始值的控制

\n\n

与reduce不同,fold要求显式指定初始值。这给了你完全的控制权,更重要的是,允许处理空集合。

\n\n
val numbers = listOf(1, 2, 3, 4, 5)\nval sum = numbers.fold(0) { acc, i -> acc + i }\nprintln(sum) // 15\n\nval emptyList = listOf<Int>()\nval emptySum = emptyList.fold(0) { acc, i -> acc + i }\nprintln(emptySum) // 0,没有错误!
\n\n

看到区别了吗?如果集合为空,fold返回初始值。而reduce在这种情况下会崩溃。

\n\n

Kotlin中fold和reduce的关键区别

\n\n

让我们系统化这些知识。以下表格将帮助你快速定位:

\n\n
    \n
  • 初始值:在fold中,你自行设定。在reduce中,它是集合的第一个元素。
  • \n
  • 结果类型:在fold中,结果类型可以与元素类型不同(例如,累加Int,得到String)。在reduce中,结果类型始终与元素类型相同。
  • \n
  • 空集合:fold能正常处理(返回初始值)。reduce会抛出异常。
  • \n
  • 性能:两个函数的时间复杂度都是O(n)。性能差异可以忽略不计。
  • \n
\n\n

现在,让我们在代码中看看这一点。

\n\n

示例1:累加器和元素的不同类型

\n\n

假设我们有一个数字列表,我们想得到一个字符串——它们的和以可读形式呈现。fold完美胜任,因为累加器类型(String)与元素类型(Int)不同。

\n\n
val numbers = listOf(1, 2, 3)\nval result = numbers.fold("总和: ") { acc, i -> "$acc$i " }\nprintln(result) // "总和: 1 2 3 "
\n\n

尝试用reduce做同样的事情——编译器会报错,因为reduce要求累加器类型与元素类型相同。

\n\n

示例2:考虑初始值的求和计算

\n\n

一个常见任务:计算订单的总金额,但我们账户中已有初始余额。

\n\n
val orders = listOf(100, 250, 75)\nval initialBalance = 500\nval totalBalance = orders.fold(initialBa                

博客

书籍推荐