匿名函数与Lambda #
一、匿名函数基础 #
1.1 什么是匿名函数 #
匿名函数(也叫 Lambda 表达式)是没有名称的函数,通常作为参数传递给高阶函数。
1.2 基本语法 #
scala
(parameters) => body
1.3 简单示例 #
scala
val double = (x: Int) => x * 2
val add = (a: Int, b: Int) => a + b
val greet = (name: String) => s"Hello, $name!"
double(5)
add(10, 20)
greet("Scala")
二、匿名函数语法 #
2.1 单参数 #
scala
val isEven = (x: Int) => x % 2 == 0
val square = (x: Int) => x * x
val length = (s: String) => s.length
2.2 多参数 #
scala
val add = (a: Int, b: Int) => a + b
val max = (a: Int, b: Int) => if a > b then a else b
val format = (name: String, age: Int) => s"$name is $age years old"
2.3 无参数 #
scala
val getTimestamp = () => System.currentTimeMillis()
val random = () => scala.util.Random.nextInt()
getTimestamp()
random()
2.4 块表达式体 #
scala
val process = (x: Int) => {
val doubled = x * 2
val squared = doubled * doubled
squared
}
val validate = (age: Int) => {
if age < 0 then Left("Invalid age")
else if age > 150 then Left("Age too high")
else Right(age)
}
三、占位符语法 #
3.1 单占位符 #
当参数只使用一次时,可以用 _ 代替:
scala
val numbers = List(1, 2, 3, 4, 5)
numbers.map(x => x * 2)
numbers.map(_ * 2)
numbers.filter(x => x > 3)
numbers.filter(_ > 3)
numbers.foreach(x => println(x))
numbers.foreach(println(_))
numbers.foreach(println)
3.2 多占位符 #
scala
val add = (_: Int) + (_: Int)
val multiply = (_: Int) * (_: Int)
val numbers = List(1, 2, 3, 4, 5)
numbers.reduce((a, b) => a + b)
numbers.reduce(_ + _)
3.3 占位符的限制 #
占位符只能用于每个参数使用一次的情况:
scala
val double = (x: Int) => x * x
val double2 = _ * _
val diff = (a: Int, b: Int) => a - b
val diff2 = _ - _
val selfAdd = (x: Int) => x + x
3.4 类型推断 #
scala
val list = List(1, 2, 3, 4, 5)
list.map(_ * 2)
list.filter(_ > 3)
list.reduce(_ + _)
val strings = List("hello", "world")
strings.map(_.toUpperCase)
strings.filter(_.length > 4)
四、闭包 #
4.1 捕获外部变量 #
匿名函数可以捕获定义作用域中的变量:
scala
val factor = 10
val multiplier = (x: Int) => x * factor
multiplier(5)
4.2 修改捕获的变量 #
scala
var sum = 0
val numbers = List(1, 2, 3, 4, 5)
numbers.foreach(x => sum += x)
println(sum)
4.3 闭包示例 #
scala
def makeCounter(): () => Int =
var count = 0
() =>
count += 1
count
val counter1 = makeCounter()
val counter2 = makeCounter()
counter1()
counter1()
counter2()
4.4 闭包与函数返回 #
scala
def makeAdder(x: Int): Int => Int =
y => x + y
val addFive = makeAdder(5)
val addTen = makeAdder(10)
addFive(3)
addTen(3)
五、匿名函数作为参数 #
5.1 传递给高阶函数 #
scala
val numbers = List(1, 2, 3, 4, 5)
val doubled = numbers.map((x: Int) => x * 2)
val evens = numbers.filter((x: Int) => x % 2 == 0)
val sum = numbers.reduce((a: Int, b: Int) => a + b)
5.2 类型推断 #
scala
val numbers = List(1, 2, 3, 4, 5)
val doubled = numbers.map(x => x * 2)
val evens = numbers.filter(x => x % 2 == 0)
val sum = numbers.reduce((a, b) => a + b)
5.3 简化形式 #
scala
val numbers = List(1, 2, 3, 4, 5)
val doubled = numbers.map(_ * 2)
val evens = numbers.filter(_ % 2 == 0)
val sum = numbers.reduce(_ + _)
六、匿名函数类型 #
6.1 函数类型语法 #
scala
val f1: Int => Int = x => x * 2
val f2: (Int, Int) => Int = (a, b) => a + b
val f3: () => String = () => "Hello"
val f4: String => Int => String = s => n => s * n
6.2 FunctionN 特质 #
scala
val f1: Function1[Int, Int] = x => x * 2
val f2: Function2[Int, Int, Int] = (a, b) => a + b
val f3: Function0[String] = () => "Hello"
6.3 方法转函数 #
scala
def double(x: Int): Int = x * 2
val doubleFunc: Int => Int = double
val doubleFunc2 = double _
七、模式匹配中的匿名函数 #
7.1 使用模式匹配 #
scala
val describe: Any => String = {
case i: Int => s"Int: $i"
case s: String => s"String: $s"
case _ => "Unknown"
}
describe(42)
describe("hello")
describe(3.14)
7.2 偏函数 #
scala
val divide: PartialFunction[Int, Int] = {
case d if d != 0 => 10 / d
}
divide.isDefinedAt(0)
divide.isDefinedAt(2)
divide(2)
7.3 collect 方法 #
scala
val numbers = List(1, 2, 3, 4, 5)
val evenStrings = numbers.collect {
case n if n % 2 == 0 => s"even: $n"
}
八、实用示例 #
8.1 排序 #
scala
case class Person(name: String, age: Int)
val people = List(
Person("Alice", 25),
Person("Bob", 30),
Person("Charlie", 20)
)
val byAge = people.sortBy(_.age)
val byName = people.sortBy(_.name)
val byAgeDesc = people.sortWith((a, b) => a.age > b.age)
8.2 分组 #
scala
val words = List("apple", "banana", "cherry", "date")
val byLength = words.groupBy(_.length)
val byFirstChar = words.groupBy(_.head)
8.3 聚合 #
scala
case class Sale(product: String, amount: Double)
val sales = List(
Sale("A", 100),
Sale("B", 200),
Sale("A", 150),
Sale("B", 250)
)
val byProduct = sales.groupMapReduce(_.product)(_.amount)(_ + _)
8.4 链式操作 #
scala
val result = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
.filter(_ % 2 == 0)
.map(_ * 2)
.take(3)
.sum
九、匿名函数最佳实践 #
9.1 保持简洁 #
scala
list.map(_ * 2)
list.filter(_ > 0)
list.map(x => x * x + 2 * x + 1)
9.2 使用有意义的参数名 #
scala
people.sortWith((p1, p2) => p1.age < p2.age)
people.sortWith((person1, person2) => person1.age < person2.age)
9.3 复杂逻辑使用命名函数 #
scala
def isEligible(person: Person): Boolean =
person.age >= 18 && person.score > 60
people.filter(isEligible)
9.4 使用 for 推导式替代复杂链式调用 #
scala
val result = list
.filter(_ > 0)
.map(_ * 2)
.filter(_ < 100)
.map(_.toString)
val result2 = for
x <- list
if x > 0
doubled = x * 2
if doubled < 100
yield doubled.toString
十、总结 #
语法对比 #
| 语法 | 示例 |
|---|---|
| 完整形式 | (x: Int) => x * 2 |
| 类型推断 | x => x * 2 |
| 占位符 | _ * 2 |
| 多参数 | (a, b) => a + b |
| 多占位符 | _ + _ |
最佳实践 #
- 简单操作使用占位符语法
- 复杂逻辑使用命名函数
- 使用有意义的参数名
- 考虑使用 for 推导式提高可读性
下一步,让我们学习 柯里化!
最后更新:2026-03-27