题目
使用Scala实现列表元素求和
信息
- 类型:问答
- 难度:⭐
考点
高阶函数, 不可变性, 递归
快速回答
在Scala中实现列表求和有三种常用方式:
- 使用
sum内置方法:List(1,2,3).sum - 使用
foldLeft高阶函数:list.foldLeft(0)(_ + _) - 使用递归模式匹配:
def sum(list: List[Int]): Int = list match { case Nil => 0 case head :: tail => head + sum(tail) }
问题背景
在函数式编程中,对集合进行聚合操作是最基础的任务之一。列表求和能很好考察候选人对Scala核心特性的理解。
解决方案
1. 使用内置sum方法(最简单)
val numbers = List(1, 2, 3, 4)
val total = numbers.sum // 结果: 10原理说明:Scala标准库为数值型集合提供了sum方法,内部通过隐式参数获取数值类型的加法操作。
2. 使用foldLeft高阶函数(推荐)
val total = numbers.foldLeft(0)((acc, x) => acc + x)
// 简写: numbers.foldLeft(0)(_ + _)原理说明:
foldLeft是左折叠操作,从列表头部开始遍历- 第一个参数
0是初始累加值 - 第二个参数是合并函数
(累加值, 当前元素) => 新累加值 - 符合不可变性原则:不修改原始列表,返回新结果
最佳实践:
- 优先使用
foldLeft而非foldRight(避免栈溢出) - 对于数值操作可用
sum,但foldLeft适用更广的场景
3. 递归实现(展示FP核心思想)
def sum(list: List[Int]): Int = list match {
case Nil => 0 // 空列表返回0
case head :: tail => head + sum(tail) // 头元素+剩余列表的和
}
sum(List(1,2,3)) // 返回6原理说明:
- 使用模式匹配解构列表
Nil表示空列表(递归终止条件)head :: tail将列表分解为第一个元素和剩余部分- 通过递归调用处理子列表
常见错误
- 可变变量:错误使用
var累加(违反不可变性)// 反例(命令式风格) var total = 0 for (x <- numbers) total += x - 缺少终止条件:递归实现忘记处理
Nil情况会导致MatchError - 尾递归优化:递归版本可能栈溢出,应使用
@tailrec优化:import scala.annotation.tailrec @tailrec def sumTailRec(list: List[Int], acc: Int = 0): Int = list match { case Nil => acc case head :: tail => sumTailRec(tail, acc + head) }
扩展知识
- foldLeft vs reduce:
reduce不需要初始值但要求非空集合 - 泛型实现:使用类型参数支持更多数值类型
def sumGeneric[T](list: List[T])(implicit num: Numeric[T]): T = list.foldLeft(num.zero)(num.plus) - 并行计算:大数据集可使用
par转换为并行集合加速numbers.par.sum // 并行求和