Scala 循环

在 Scala 中,循环是用于重复执行代码块的控制结构。Scala 提供多种循环方式,包括 for 循环、while 循环和 do-while 循环,同时支持函数式编程风格的循环替代方案(如集合操作)。Scala 强调简洁和不可变性,因此函数式方法(如 mapforeach)通常比传统循环更受欢迎。以下是对 Scala 循环的中文讲解,内容简洁清晰,涵盖语法、用法、特性及注意事项,适合初学者理解。


1. 循环概述

  • 定义:循环用于重复执行一段代码,直到满足特定条件。
  • 特点
  • Scala 提供传统的命令式循环(for, while, do-while)。
  • 函数式编程中,推荐使用集合操作(如 map, filter, foreach)替代循环。
  • for 循环支持强大的推导式(comprehension)语法,可生成值。
  • 用途:处理重复任务、遍历集合或执行条件控制的迭代。

2. Scala 循环类型及语法

1. for 循环

  • 定义for 循环用于遍历集合、范围或执行多条件迭代,支持推导式。
  • 语法
  for (变量 <- 迭代器) {
    // 代码块
  }

或作为表达式(推导式):

  val result = for (变量 <- 迭代器) yield 值
  • 常见用法
  • 遍历范围
    scala for (i <- 1 to 5) { println(i) }
    输出
    1 2 3 4 5
    • to:包含结束值。
    • until:不包含结束值(1 until 5 遍历 1 到 4)。
  • 遍历集合
    scala val fruits = List("apple", "banana", "orange") for (fruit <- fruits) { println(fruit) }
    输出
    apple banana orange
  • 多重循环
    scala for (i <- 1 to 3; j <- 1 to 2) { println(s"i=$i, j=$j") }
    输出
    i=1, j=1 i=1, j=2 i=2, j=1 i=2, j=2 i=3, j=1 i=3, j=2
  • 带条件过滤
    scala for (i <- 1 to 5 if i % 2 == 0) { println(i) }
    输出
    2 4
  • 推导式(生成新集合)val evens = for (i <- 1 to 5 if i % 2 == 0) yield i println(evens) // 输出: Vector(2, 4)
  • 特点
  • for 循环可以嵌套,条件用 if 过滤。
  • 推导式(yield)返回新集合,符合函数式编程。
  • 支持多变量和复杂条件。

2. while 循环

  • 定义:在条件为 true 时重复执行代码块,适合不确定迭代次数的场景。
  • 语法
  while (条件) {
    // 代码块
  }
  • 示例
  var i = 1
  while (i <= 5) {
    println(i)
    i += 1
  }

输出

  1
  2
  3
  4
  5
  • 特点
  • 需要手动更新循环变量(如 i += 1),否则可能导致死循环。
  • 不返回值的命令式循环,返回类型为 Unit

3. do-while 循环

  • 定义:先执行一次代码块,再检查条件,适合至少执行一次的场景。
  • 语法
  do {
    // 代码块
  } while (条件)
  • 示例
  var i = 6
  do {
    println(i)
    i += 1
  } while (i <= 5)

输出

  6
  • 即使条件不满足(i <= 5false),代码块仍执行一次。

3. 函数式循环替代

Scala 鼓励函数式编程,常用集合方法替代传统循环:

  • foreach:遍历集合,执行操作,无返回值。
  List(1, 2, 3).foreach(x => println(x))

输出

  1
  2
  3
  • map:遍历并转换元素,返回新集合。
  val doubled = List(1, 2, 3).map(_ * 2)
  println(doubled) // 输出: List(2, 4, 6)
  • filter:筛选符合条件的元素。
  val evens = List(1, 2, 3, 4).filter(_ % 2 == 0)
  println(evens) // 输出: List(2, 4)
  • 优点
  • 不可变,线程安全。
  • 代码简洁,符合函数式编程理念。
  • 避免手动管理循环变量。

4. 循环控制

Scala 不支持 breakcontinue 关键字,但可以通过以下方式实现:

  • 使用 return:提前退出方法。
  def findFirstEven(numbers: List[Int]): Int = {
    for (n <- numbers) {
      if (n % 2 == 0) return n
    }
    -1
  }
  println(findFirstEven(List(1, 3, 4, 5))) // 输出: 4
  • 使用 scala.util.control.Breaks
  import scala.util.control.Breaks._

  breakable {
    for (i <- 1 to 5) {
      if (i == 3) break // 退出循环
      println(i)
    }
  }

输出

  1
  2
  • 条件过滤:用 if 替代 continue
  for (i <- 1 to 5 if i % 2 == 0) {
    println(i) // 只打印偶数
  }

输出

  2
  4

5. 注意事项

  • 优先函数式方法:Scala 鼓励用 map, filter, foreach 替代 whiledo-while,减少副作用。
  • 避免死循环while 循环需确保条件最终变为 false
  • 类型安全:循环条件必须是 Boolean 类型:
  // while (5) println("Error") // 错误:5 不是 Boolean
  • 推导式返回值for 推导式返回 Vector(Scala 2)或 List(Scala 3,视上下文)。
  • Scala 2 vs Scala 3
  • Scala 3 简化了 for 语法(如允许省略括号),但核心功能一致。
  • Scala 3 的推导式更灵活,错误提示更友好。
  • 性能:函数式方法(如 map)可能生成新集合,内存开销稍高,但更安全。

6. 实践示例

综合示例,展示多种循环和函数式替代:

object LoopDemo {
  def main(args: Array[String]): Unit = {
    // for 循环:遍历范围
    println("for 循环:")
    for (i <- 1 to 3) {
      println(i)
    }

    // for 推导式
    println("for 推导式:")
    val squares = for (i <- 1 to 3) yield i * i
    println(squares) // 输出: Vector(1, 4, 9)

    // while 循环
    println("while 循环:")
    var i = 1
    while (i <= 3) {
      println(i)
      i += 1
    }

    // do-while 循环
    println("do-while 循环:")
    var j = 4
    do {
      println(j)
      j += 1
    } while (j <= 3)

    // 函数式替代
    println("函数式循环:")
    List(1, 2, 3).foreach(println)

    // 使用 break
    import scala.util.control.Breaks._
    println("带 break 的循环:")
    breakable {
      for (i <- 1 to 5) {
        if (i == 3) break
        println(i)
      }
    }
  }
}

输出

for 循环:
1
2
3
for 推导式:
Vector(1, 4, 9)
while 循环:
1
2
3
do-while 循环:
4
函数式循环:
1
2
3
带 break 的循环:
1
2

7. 学习建议

  • 实践:在 Scala REPL(运行 scala 命令)中测试 for 推导式和 while 循环,比较与函数式方法的差异。
  • 函数式思维:优先使用 map, filter, foreach,减少 var 和命令式循环。
  • 控制流:熟悉 breakablereturn 的使用,但尽量用条件过滤替代。
  • 资源
  • 官方文档:https://www.scala-lang.org/
  • Scala Exercises (https://www.scala-exercises.org/)
  • 《Programming in Scala》by Martin Odersky

如果需要深入讲解某一循环类型(如 for 推导式或函数式替代)或更多示例,请告诉我!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注