Scala 从入门到精通学习笔记

Scala 从入门到精通学习笔记

1. Scala 基础

1.1 什么是 Scala?

Scala = Scalable Language(可扩展的语言)

特点

  • 🔥 多范式:面向对象 + 函数式编程
  • 运行在 JVM:与 Java 完全互操作
  • 📦 类型推断:简洁但类型安全
  • 🎯 表达力强:代码量约为 Java 的 1/3

1.2 第一个 Scala 程序

// HelloWorld.scala
object HelloWorld {
  def main(args: Array[String]): Unit = {
    println("Hello, Scala!")
  }
}

// 编译运行
// scalac HelloWorld.scala
// scala HelloWorld

解释

  • object:单例对象,类似 Java 的静态类
  • def:定义函数/方法
  • Unit:相当于 Java 的 void
  • println:打印并换行

1.3 Scala 脚本模式

// hello.scala (脚本文件)
println("Hello, Scala!")

// 直接运行,无需编译
// scala hello.scala

解释:脚本模式不需要 main 方法,适合快速测试


2. 变量与数据类型

2.1 变量声明

// val: 不可变变量(推荐,类似 Java 的 final)
val x = 10
// x = 20  // 错误!不能重新赋值

// var: 可变变量
var y = 20
y = 30  // OK

// 显式类型声明
val name: String = "Alice"
val age: Int = 25

// 类型推断
val city = "Beijing"  // 自动推断为 String

最佳实践:优先使用 val,除非确实需要修改

2.2 基本数据类型

// Scala 的所有类型都是对象,没有基本类型
val b: Byte = 127          // 8位有符号整数
val s: Short = 32767       // 16位有符号整数
val i: Int = 2147483647    // 32位有符号整数
val l: Long = 9223372036854775807L  // 64位有符号整数

val f: Float = 3.14f       // 32位浮点数
val d: Double = 3.1415926  // 64位浮点数

val c: Char = 'A'          // 16位 Unicode 字符
val bool: Boolean = true   // 布尔值

val str: String = "Hello"  // 字符串

// 类型层次(所有类型的父类)
val any: Any = 42          // Any 是所有类型的父类
val anyVal: AnyVal = 10    // 值类型的父类
val anyRef: AnyRef = "Hi"  // 引用类型的父类

类型层次图

        Any
       /   \
   AnyVal  AnyRef
   /  |  \    |
 Int Long ... String, List, ...

2.3 字符串操作

// 字符串插值
val name = "Alice"
val age = 25

// s 插值器(变量替换)
val msg1 = s"My name is $name"
val msg2 = s"Next year I'll be ${age + 1}"

// f 插值器(格式化)
val pi = 3.1415926
val formatted = f"Pi is $pi%.2f"  // Pi is 3.14

// raw 插值器(原始字符串,不转义)
val raw = raw"Line1\nLine2"  // 输出 Line1\nLine2

// 多行字符串
val multiLine = 
  """This is line 1
    |This is line 2
    |This is line 3""".stripMargin

// 字符串方法
val text = "Hello Scala"
println(text.length)           // 11
println(text.toUpperCase)      // HELLO SCALA
println(text.toLowerCase)      // hello scala
println(text.split(" "))       // Array(Hello, Scala)
println(text.startsWith("He")) // true
println(text.contains("Sca"))  // true
println(text.substring(0, 5))  // Hello

2.4 类型转换

// 自动类型提升(低精度 → 高精度)
val a: Int = 10
val b: Double = a  // Int 自动转 Double

// 强制类型转换
val x: Double = 3.14
val y: Int = x.toInt  // 3(截断小数)

// 转换方法
val num = 42
num.toByte
num.toShort
num.toInt
num.toLong
num.toFloat
num.toDouble
num.toChar
num.toString

// 字符串转数字
val str = "123"
val n1 = str.toInt      // 123
val n2 = str.toDouble   // 123.0

3. 运算符

3.1 算术运算符

val a = 10
val b = 3

println(a + b)   // 13 加法
println(a - b)   // 7  减法
println(a * b)   // 30 乘法
println(a / b)   // 3  除法(整数)
println(a % b)   // 1  取模

// Scala 中运算符实际上是方法
println(a.+(b))  // 等同于 a + b

重要:在 Scala 中,+ - * / 等都是方法调用,a + b 实际是 a.+(b)

3.2 关系运算符

val x = 5
val y = 10

println(x == y)  // false 等于
println(x != y)  // true  不等于
println(x > y)   // false 大于
println(x < y)   // true  小于
println(x >= y)  // false 大于等于
println(x <= y)  // true  小于等于

3.3 逻辑运算符

val a = true
val b = false

println(a && b)  // false 逻辑与
println(a || b)  // true  逻辑或
println(!a)      // false 逻辑非

3.4 位运算符

val a = 60  // 二进制: 0011 1100
val b = 13  // 二进制: 0000 1101

println(a & b)   // 12  按位与
println(a | b)   // 61  按位或
println(a ^ b)   // 49  按位异或
println(~a)      // -61 按位取反
println(a << 2)  // 240 左移
println(a >> 2)  // 15  右移
println(a >>> 2) // 15  无符号右移

3.5 赋值运算符

var x = 10

x += 5   // x = x + 5  → 15
x -= 3   // x = x - 3  → 12
x *= 2   // x = x * 2  → 24
x /= 4   // x = x / 4  → 6
x %= 5   // x = x % 5  → 1

4. 流程控制

4.1 if-else 表达式

重要特性:Scala 的 if-else 是表达式,有返回值

// 基本 if-else
val age = 18
if (age >= 18) {
  println("成年人")
} else {
  println("未成年")
}

// if-else 作为表达式(有返回值)
val result = if (age >= 18) "成年人" else "未成年"
println(result)

// 多分支
val score = 85
val grade = if (score >= 90) {
  "优秀"
} else if (score >= 80) {
  "良好"
} else if (score >= 60) {
  "及格"
} else {
  "不及格"
}
println(s"成绩等级: $grade")

// if 没有 else 时,else 默认返回 Unit
val x = if (true) 1
println(x)  // 1

val y = if (false) 1
println(y)  // () 即 Unit

4.2 for 循环

// 基本 for 循环(范围)
for (i <- 1 to 5) {
  println(i)  // 1 2 3 4 5
}

// until(不包含结束值)
for (i <- 1 until 5) {
  println(i)  // 1 2 3 4
}

// 步长
for (i <- 1 to 10 by 2) {
  println(i)  // 1 3 5 7 9
}

// 倒序
for (i <- 10 to 1 by -1) {
  println(i)  // 10 9 8 ... 1
}

// 遍历集合
val list = List("Alice", "Bob", "Charlie")
for (name <- list) {
  println(name)
}

// 嵌套循环
for (i <- 1 to 3; j <- 1 to 3) {
  println(s"($i, $j)")
}

// 守卫(条件过滤)
for (i <- 1 to 10 if i % 2 == 0) {
  println(i)  // 2 4 6 8 10
}

// for 推导式(yield 返回新集合)
val squares = for (i <- 1 to 5) yield i * i
println(squares)  // Vector(1, 4, 9, 16, 25)

// 复杂推导
val result = for {
  i <- 1 to 3
  j <- 1 to 3
  if i != j
} yield (i, j)
println(result)  // Vector((1,2), (1,3), (2,1), (2,3), (3,1), (3,2))

4.3 while 循环

// while 循环
var i = 1
while (i <= 5) {
  println(i)
  i += 1
}

// do-while 循环
var j = 1
do {
  println(j)
  j += 1
} while (j <= 5)

注意:Scala 推荐使用函数式风格(map, filter 等)而非 while 循环

4.4 循环控制

import scala.util.control.Breaks._

// break 示例(Scala 需要导入 Breaks)
breakable {
  for (i <- 1 to 10) {
    if (i == 5) break
    println(i)  // 1 2 3 4
  }
}

// 嵌套循环的 break
breakable {
  for (i <- 1 to 3) {
    breakable {
      for (j <- 1 to 3) {
        if (j == 2) break
        println(s"($i, $j)")
      }
    }
  }
}

注意:Scala 没有 continue,推荐使用 if 条件过滤


5. 函数

5.1 函数定义

// 基本函数定义
def add(a: Int, b: Int): Int = {
  a + b
}

// 单行函数可以省略大括号
def add2(a: Int, b: Int): Int = a + b

// 类型推断(返回类型可省略)
def add3(a: Int, b: Int) = a + b

// 无参数函数
def sayHello(): Unit = {
  println("Hello!")
}

// 调用
sayHello()    // 带括号
sayHello      // 可以省略括号(如果定义时没有括号)

// 定义时没有括号
def currentTime = System.currentTimeMillis()
println(currentTime)  // 调用时不能加括号

// 无返回值函数(Unit)
def printSum(a: Int, b: Int): Unit = {
  println(a + b)
}

5.2 参数

// 默认参数
def greet(name: String, msg: String = "Hello") = {
  s"$msg, $name!"
}

println(greet("Alice"))              // Hello, Alice!
println(greet("Bob", "Hi"))          // Hi, Bob!

// 命名参数
println(greet(msg = "Wel***e", name = "Charlie"))

// 可变参数
def sum(numbers: Int*): Int = {
  var total = 0
  for (num <- numbers) {
    total += num
  }
  total
}

println(sum(1, 2, 3))        // 6
println(sum(1, 2, 3, 4, 5))  // 15

// 传递序列作为可变参数
val nums = List(1, 2, 3, 4)
println(sum(nums: _*))  // 使用 :_* 展开序列

5.3 函数类型

// 函数也是对象,可以赋值给变量
val add: (Int, Int) => Int = (a, b) => a + b
println(add(3, 5))  // 8

// 匿名函数(Lambda)
val multiply = (a: Int, b: Int) => a * b
println(multiply(4, 5))  // 20

// 简化写法(占位符)
val increment = (_: Int) + 1
println(increment(5))  // 6

val sum = (_: Int) + (_: Int)
println(sum(3, 7))  // 10

// 函数作为参数
def operate(a: Int, b: Int, f: (Int, Int) => Int): Int = {
  f(a, b)
}

println(operate(10, 5, (x, y) => x + y))  // 15
println(operate(10, 5, _ * _))            // 50

5.4 高阶函数

// 返回函数的函数
def multiplier(factor: Int): Int => Int = {
  (x: Int) => x * factor
}

val triple = multiplier(3)
println(triple(5))  // 15

val double = multiplier(2)
println(double(8))  // 16

// 柯里化(Currying)
def add(a: Int)(b: Int): Int = a + b

println(add(3)(5))  // 8

val add5 = add(5) _
println(add5(10))  // 15

// 实用示例:自定义比较器
def customSort(list: List[Int])(***pare: (Int, Int) => Boolean): List[Int] = {
  list.sortWith(***pare)
}

val numbers = List(3, 1, 4, 1, 5, 9)
println(customSort(numbers)(_ < _))  // 升序
println(customSort(numbers)(_ > _))  // 降序

5.5 递归函数

// 递归必须显式声明返回类型
def factorial(n: Int): Int = {
  if (n <= 1) 1
  else n * factorial(n - 1)
}

println(factorial(5))  // 120

// 尾递归优化(@tailrec 注解)
import scala.annotation.tailrec

@tailrec
def factorialTail(n: Int, a***: Int = 1): Int = {
  if (n <= 1) a***
  else factorialTail(n - 1, n * a***)
}

println(factorialTail(5))  // 120

// 斐波那契数列
def fibona***i(n: Int): Int = {
  if (n <= 1) n
  else fibona***i(n - 1) + fibona***i(n - 2)
}

println(fibona***i(10))  // 55

6. 集合

6.1 数组 (Array)

// 创建数组
val arr1 = Array(1, 2, 3, 4, 5)
val arr2 = new Array[Int](5)  // 5个元素,默认值0

// 访问元素
println(arr1(0))  // 1(注意:使用圆括号)
arr1(0) = 10      // 修改元素

// 数组遍历
for (elem <- arr1) {
  println(elem)
}

// 使用索引遍历
for (i <- arr1.indices) {
  println(s"arr1($i) = ${arr1(i)}")
}

// 数组方法
println(arr1.length)       // 5
println(arr1.max)          // 10
println(arr1.min)          // 2
println(arr1.sum)          // 20

// 多维数组
val matrix = Array.ofDim[Int](3, 4)  // 3行4列
matrix(0)(0) = 1
matrix(1)(2) = 5

// 可变长数组(ArrayBuffer)
import scala.collection.mutable.ArrayBuffer

val buffer = ArrayBuffer[Int]()
buffer += 1           // 添加元素
buffer += (2, 3, 4)   // 添加多个
buffer ++= List(5, 6) // 添加集合

buffer -= 3           // 删除元素
buffer.remove(0)      // 删除索引0的元素

println(buffer)  // ArrayBuffer(2, 4, 5, 6)

// 转换
val arr = buffer.toArray   // ArrayBuffer → Array
val buf = arr.toBuffer     // Array → ArrayBuffer

6.2 列表 (List)

特点:不可变、链表结构

// 创建列表
val list1 = List(1, 2, 3, 4, 5)
val list2 = 1 :: 2 :: 3 :: Nil  // 使用 :: 构造
val list3 = List.range(1, 10)   // 1 到 9

// 访问元素
println(list1.head)      // 1(第一个元素)
println(list1.tail)      // List(2, 3, 4, 5)(除第一个外的其他)
println(list1(2))        // 3(索引访问)
println(list1.last)      // 5(最后一个)
println(list1.init)      // List(1, 2, 3, 4)(除最后一个外的其他)

// 列表操作(返回新列表)
val list4 = 0 :: list1        // 在头部添加
val list5 = list1 :+ 6        // 在尾部添加
val list6 = list1 ++ list2    // 连接列表

// 列表方法
println(list1.isEmpty)        // false
println(list1.length)         // 5
println(list1.reverse)        // List(5, 4, 3, 2, 1)
println(list1.take(3))        // List(1, 2, 3)
println(list1.drop(2))        // List(3, 4, 5)
println(list1.contains(3))    // true

// 可变列表(ListBuffer)
import scala.collection.mutable.ListBuffer

val buffer2 = ListBuffer[Int]()
buffer2 += 1
buffer2 += (2, 3)
buffer2.append(4)
buffer2.prepend(0)

println(buffer2)  // ListBuffer(0, 1, 2, 3, 4)

6.3 集合 (Set)

特点:不重复、无序

// 不可变 Set
val set1 = Set(1, 2, 3, 4, 5)
val set2 = Set(4, 5, 6, 7, 8)

// Set 操作
println(set1.contains(3))      // true
println(set1(3))               // true(与 contains 等价)

// 集合运算
println(set1 & set2)           // Set(4, 5) 交集
println(set1 | set2)           // Set(1,2,3,4,5,6,7,8) 并集
println(set1 &~ set2)          // Set(1, 2, 3) 差集

// 添加删除(返回新 Set)
val set3 = set1 + 6            // 添加元素
val set4 = set1 - 3            // 删除元素
val set5 = set1 ++ Set(6, 7)  // 添加多个

// 可变 Set
import scala.collection.mutable

val mutableSet = mutable.Set(1, 2, 3)
mutableSet += 4                // 添加
mutableSet -= 2                // 删除
mutableSet.add(5)              // 添加(返回 Boolean)
mutableSet.remove(1)           // 删除(返回 Boolean)

println(mutableSet)  // Set(3, 4, 5)

6.4 映射 (Map)

特点:键值对、键唯一

// 不可变 Map
val map1 = Map("Alice" -> 25, "Bob" -> 30, "Charlie" -> 35)
val map2 = Map(("Alice", 25), ("Bob", 30))  // 等价写法

// 访问元素
println(map1("Alice"))         // 25
println(map1.get("Alice"))     // Some(25)
println(map1.get("David"))     // None
println(map1.getOrElse("David", 0))  // 0(默认值)

// Map 操作
println(map1.keys)             // Set(Alice, Bob, Charlie)
println(map1.values)           // Iterable(25, 30, 35)
println(map1.contains("Bob"))  // true

// 添加删除(返回新 Map)
val map3 = map1 + ("David" -> 28)
val map4 = map1 - "Bob"
val map5 = map1 ++ Map("Eve" -> 22, "Frank" -> 27)

// 可变 Map
import scala.collection.mutable

val mutableMap = mutable.Map("Alice" -> 25)
mutableMap("Bob") = 30         // 添加/更新
mutableMap += ("Charlie" -> 35)
mutableMap -= "Alice"          // 删除
mutableMap.put("David", 28)    // 添加(返回 Option)
mutableMap.remove("Bob")       // 删除(返回 Option)

println(mutableMap)  // Map(Charlie -> 35, David -> 28)

// 遍历 Map
for ((key, value) <- map1) {
  println(s"$key: $value")
}

6.5 元组 (Tuple)

特点:不同类型元素的组合、不可变

// 创建元组
val tuple1 = (1, "Alice", 25)
val tuple2 = ("Bob", 30, true)
val pair = ("key", "value")  // 常用于 Map

// 访问元素(从 1 开始)
println(tuple1._1)  // 1
println(tuple1._2)  // Alice
println(tuple1._3)  // 25

// 模式匹配解构
val (id, name, age) = tuple1
println(s"ID: $id, Name: $name, Age: $age")

// 元组最多 22 个元素
val bigTuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
                11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22)

// 交换元组(只适用于二元组)
val swapped = pair.swap  // ("value", "key")

6.6 常用集合方法

val numbers = List(1, 2, 3, 4, 5)

// map: 映射
println(numbers.map(_ * 2))  // List(2, 4, 6, 8, 10)

// filter: 过滤
println(numbers.filter(_ % 2 == 0))  // List(2, 4)

// foreach: 遍历
numbers.foreach(println)

// reduce: 归约
println(numbers.reduce(_ + _))  // 15

// fold: 带初始值的归约
println(numbers.fold(10)(_ + _))  // 25

// flatMap: 扁平映射
val nested = List(List(1, 2), List(3, 4))
println(nested.flatMap(x => x))  // List(1, 2, 3, 4)

// zip: 拉链
val list1 = List(1, 2, 3)
val list2 = List("a", "b", "c")
println(list1.zip(list2))  // List((1,a), (2,b), (3,c))

// groupBy: 分组
val words = List("apple", "banana", "avocado", "cherry")
println(words.groupBy(_.charAt(0)))
// Map(a -> List(apple, avocado), b -> List(banana), c -> List(cherry))

// sorted: 排序
println(List(3, 1, 4, 1, 5).sorted)  // List(1, 1, 3, 4, 5)

// sortBy: 按某字段排序
case class Person(name: String, age: Int)
val people = List(Person("Alice", 25), Person("Bob", 20))
println(people.sortBy(_.age))

// distinct: 去重
println(List(1, 2, 2, 3, 3, 3).distinct)  // List(1, 2, 3)

7. 面向对象编程

7.1 类和对象

// 定义类
class Person {
  var name: String = ""
  var age: Int = 0
  
  def greet(): Unit = {
    println(s"Hello, I'm $name")
  }
}

// 创建对象
val person = new Person()
person.name = "Alice"
person.age = 25
person.greet()

// 带构造参数的类
class Student(val name: String, val age: Int) {
  // val: 只读属性
  // var: 可读写属性
  // 不加修饰符: 私有属性
  
  def study(): Unit = {
    println(s"$name is studying")
  }
}

val student = new Student("Bob", 20)
println(student.name)  // Bob
student.study()

// 辅助构造器
class Teacher(val name: String, val age: Int) {
  var subject: String = ""
  
  // 辅助构造器(必须调用主构造器)
  def this(name: String, age: Int, subject: String) {
    this(name, age)
    this.subject = subject
  }
  
  def teach(): Unit = {
    println(s"$name teaches $subject")
  }
}

val teacher1 = new Teacher("Alice", 30)
val teacher2 = new Teacher("Bob", 35, "Math")

7.2 单例对象 (Object)

// object 定义单例对象
object DatabaseConnection {
  private var connection: String = "Not Connected"
  
  def connect(): Unit = {
    connection = "Connected"
    println("Database connected")
  }
  
  def getStatus: String = connection
}

// 使用单例对象(不需要 new)
DatabaseConnection.connect()
println(DatabaseConnection.getStatus)

// 伴生对象(与类同名的 object)
class Circle(val radius: Double) {
  import Circle._  // 导入伴生对象
  
  def area: Double = pi * radius * radius
}

object Circle {
  private val pi = 3.14159
  
  // 工厂方法
  def apply(radius: Double): Circle = new Circle(radius)
}

// 使用 apply 方法可以省略 new
val circle1 = Circle(5.0)  // 等同于 Circle.apply(5.0)
val circle2 = new Circle(3.0)

println(circle1.area)

7.3 继承

// 父类
class Animal(val name: String) {
  def eat(): Unit = {
    println(s"$name is eating")
  }
  
  def makeSound(): Unit = {
    println("Some sound")
  }
}

// 子类(使用 extends)
class Dog(name: String, val breed: String) extends Animal(name) {
  // 重写方法(使用 override)
  override def makeSound(): Unit = {
    println(s"$name barks: Woof!")
  }
  
  def fetch(): Unit = {
    println(s"$name is fetching")
  }
}

class Cat(name: String) extends Animal(name) {
  override def makeSound(): Unit = {
    println(s"$name meows: Meow!")
  }
}

// 使用
val dog = new Dog("Buddy", "Golden Retriever")
dog.eat()        // 继承的方法
dog.makeSound()  // 重写的方法
dog.fetch()      // 自己的方法

val cat = new Cat("Whiskers")
cat.makeSound()

// 抽象类
abstract class Shape {
  // 抽象方法(无实现)
  def area: Double
  def perimeter: Double
  
  // 具体方法
  def describe(): Unit = {
    println(s"Area: $area, Perimeter: $perimeter")
  }
}

class Rectangle(val width: Double, val height: Double) extends Shape {
  override def area: Double = width * height
  override def perimeter: Double = 2 * (width + height)
}

class Circle2(val radius: Double) extends Shape {
  override def area: Double = 3.14159 * radius * radius
  override def perimeter: Double = 2 * 3.14159 * radius
}

val rect = new Rectangle(5, 3)
rect.describe()

val circle = new Circle2(4)
circle.describe()

7.4 特质 (Trait)

特质类似 Java 的接口,但更强大,可以有具体实现

// 定义特质
trait Flyable {
  def fly(): Unit = {
    println("Flying in the sky")
  }
}

trait Swimmable {
  def swim(): Unit = {
    println("Swimming in water")
  }
}

// 类可以混入多个特质(使用 with)
class Bird extends Flyable {
  override def fly(): Unit = {
    println("Bird is flying")
  }
}

class Duck extends Flyable with Swimmable {
  override def fly(): Unit = {
    println("Duck is flying")
  }
  
  override def swim(): Unit = {
    println("Duck is swimming")
  }
}

val bird = new Bird()
bird.fly()

val duck = new Duck()
duck.fly()
duck.swim()

// 特质的高级用法
trait Logger {
  def log(msg: String): Unit = {
    println(s"[LOG] $msg")
  }
}

trait TimestampLogger extends Logger {
  override def log(msg: String): Unit = {
    println(s"[${System.currentTimeMillis()}] $msg")
  }
}

class Service extends Logger {
  def doSomething(): Unit = {
    log("Doing something")
  }
}

val service = new Service()
service.doSomething()

// 动态混入特质
class BasicService {
  def work(): Unit = println("Working...")
}

val serviceWithLog = new BasicService() with Logger {
  override def work(): Unit = {
    log("Starting work")
    super.work()
    log("Work ***pleted")
  }
}

serviceWithLog.work()

7.5 样例类 (Case Class)

样例类是特殊的类,自动提供很多便利功能

// 定义样例类
case class Person(name: String, age: Int)

// 自动生成的功能:
// 1. 参数自动成为 val 属性
val person = Person("Alice", 25)
println(person.name)  // Alice

// 2. 自动生成 apply 方法(无需 new)
val person2 = Person("Bob", 30)  // 不用 new

// 3. 自动生成 toString
println(person)  // Person(Alice,25)

// 4. 自动生成 equals 和 hashCode
val person3 = Person("Alice", 25)
println(person == person3)  // true(比较内容)

// 5. 自动生成 copy 方法(复制并修改)
val person4 = person.copy(age = 26)
println(person4)  // Person(Alice,26)

// 6. 支持模式匹配
def describe(p: Person): String = p match {
  case Person("Alice", age) => s"Alice is $age years old"
  case Person(name, age) if age < 18 => s"$name is a minor"
  case Person(name, age) => s"$name is $age years old"
}

println(describe(person))   // Alice is 25 years old
println(describe(person2))  // Bob is 30 years old

// 嵌套样例类
case class Address(city: String, country: String)
case class Employee(name: String, age: Int, address: Address)

val emp = Employee("Charlie", 28, Address("Beijing", "China"))
println(emp)
println(emp.address.city)  // Beijing

// copy 深层修改
val emp2 = emp.copy(address = emp.address.copy(city = "Shanghai"))
println(emp2)

8. 模式匹配

8.1 基本模式匹配

类似 Java 的 switch,但功能更强大

// 基本匹配
val day = 3

val dayName = day match {
  case 1 => "Monday"
  case 2 => "Tuesday"
  case 3 => "Wednesday"
  case 4 => "Thursday"
  case 5 => "Friday"
  case 6 | 7 => "Weekend"  // 多个条件
  case _ => "Invalid"      // 默认情况(必须有)
}

println(dayName)  // Wednesday

// 匹配类型
def describe(x: Any): String = x match {
  case i: Int => s"Integer: $i"
  case s: String => s"String: $s"
  case d: Double => s"Double: $d"
  case l: List[_] => s"List with ${l.length} elements"
  case _ => "Unknown type"
}

println(describe(42))           // Integer: 42
println(describe("Hello"))      // String: Hello
println(describe(3.14))         // Double: 3.14
println(describe(List(1, 2, 3))) // List with 3 elements

8.2 匹配集合

// 匹配列表
def sumList(list: List[Int]): Int = list match {
  case Nil => 0                    // 空列表
  case head :: tail => head + sumList(tail)  // 递归
}

println(sumList(List(1, 2, 3, 4)))  // 10

// 匹配固定元素
def matchList(list: List[Int]): String = list match {
  case List(1, 2, 3) => "Exactly 1, 2, 3"
  case List(1, _*) => "Starts with 1"
  case x :: y :: Nil => s"Two elements: $x and $y"
  case _ => "Other"
}

println(matchList(List(1, 2, 3)))  // Exactly 1, 2, 3
println(matchList(List(1, 5, 8)))  // Starts with 1
println(matchList(List(3, 4)))     // Two elements: 3 and 4

// 匹配数组
def matchArray(arr: Array[Int]): String = arr match {
  case Array(0) => "Single zero"
  case Array(x, y) => s"Two elements: $x, $y"
  case Array(0, _*) => "Starts with zero"
  case _ => "Other"
}

println(matchArray(Array(0)))      // Single zero
println(matchArray(Array(1, 2)))   // Two elements: 1, 2
println(matchArray(Array(0, 1, 2))) // Starts with zero

// 匹配元组
def matchTuple(tuple: (Int, String)): String = tuple match {
  case (0, _) => "First element is 0"
  case (_, "hello") => "Second element is hello"
  case (x, y) => s"($x, $y)"
}

println(matchTuple((0, "world")))   // First element is 0
println(matchTuple((5, "hello")))   // Second element is hello
println(matchTuple((3, "bye")))     // (3, bye)

8.3 样例类匹配

// 样例类
case class Person(name: String, age: Int)
case class Student(name: String, age: Int, grade: String)

// 匹配样例类
def describePerson(person: Any): String = person match {
  case Person("Alice", age) => s"Alice is $age years old"
  case Person(name, age) if age < 18 => s"$name is a minor"
  case Person(name, age) => s"$name is an adult"
  case Student(name, age, grade) => s"$name is a student in grade $grade"
  case _ => "Unknown person"
}

println(describePerson(Person("Alice", 25)))  // Alice is 25 years old
println(describePerson(Person("Bob", 16)))    // Bob is a minor
println(describePerson(Student("Charlie", 20, "A")))  // Charlie is a student in grade A

// 嵌套匹配
case class Address(city: String, country: String)
case class Employee(name: String, address: Address)

def describeEmployee(emp: Employee): String = emp match {
  case Employee(name, Address("Beijing", "China")) => 
    s"$name works in Beijing, China"
  case Employee(name, Address(city, "China")) => 
    s"$name works in $city, China"
  case Employee(name, Address(city, country)) => 
    s"$name works in $city, $country"
}

val emp1 = Employee("Alice", Address("Beijing", "China"))
val emp2 = Employee("Bob", Address("Shanghai", "China"))
val emp3 = Employee("Charlie", Address("New York", "USA"))

println(describeEmployee(emp1))
println(describeEmployee(emp2))
println(describeEmployee(emp3))

8.4 守卫条件

// 在模式匹配中添加条件
def classify(x: Int): String = x match {
  case n if n < 0 => "Negative"
  case 0 => "Zero"
  case n if n > 0 && n < 10 => "Small positive"
  case n if n >= 10 => "Large positive"
}

println(classify(-5))   // Negative
println(classify(0))    // Zero
println(classify(5))    // Small positive
println(classify(15))   // Large positive

// 复杂守卫
case class Student2(name: String, scores: List[Int])

def evaluateStudent(student: Student2): String = student match {
  case Student2(name, scores) if scores.sum / scores.length >= 90 =>
    s"$name: Excellent"
  case Student2(name, scores) if scores.sum / scores.length >= 60 =>
    s"$name: Pass"
  case Student2(name, _) =>
    s"$name: Fail"
}

val s1 = Student2("Alice", List(95, 92, 98))
val s2 = Student2("Bob", List(70, 65, 75))
val s3 = Student2("Charlie", List(50, 45, 55))

println(evaluateStudent(s1))  // Alice: Excellent
println(evaluateStudent(s2))  // Bob: Pass
println(evaluateStudent(s3))  // Charlie: Fail

8.5 变量绑定

// 使用 @ 绑定变量
def processNumber(x: Int): String = x match {
  case n @ (1 | 2 | 3) => s"Small number: $n"
  case n @ _ if n > 10 => s"Large number: $n"
  case n => s"Medium number: $n"
}

println(processNumber(2))   // Small number: 2
println(processNumber(15))  // Large number: 15
println(processNumber(7))   // Medium number: 7

// 在集合中使用
def matchList2(list: List[Int]): String = list match {
  case List(_, rest @ _*) => s"First element removed, rest: $rest"
  case _ => "Empty or other"
}

println(matchList2(List(1, 2, 3, 4)))  // First element removed, rest: List(2, 3, 4)

9. 高阶函数

9.1 函数作为参数

// 接受函数作为参数
def operation(a: Int, b: Int, f: (Int, Int) => Int): Int = {
  f(a, b)
}

// 传递不同的函数
println(operation(10, 5, _ + _))  // 15
println(operation(10, 5, _ - _))  // 5
println(operation(10, 5, _ * _))  // 50
println(operation(10, 5, _ / _))  // 2

// 实用示例:通用排序
def customSort[T](list: List[T], ***pare: (T, T) => Boolean): List[T] = {
  list.sortWith(***pare)
}

val numbers = List(3, 1, 4, 1, 5, 9, 2, 6)
println(customSort(numbers, (a: Int, b: Int) => a < b))  // 升序
println(customSort(numbers, (a: Int, b: Int) => a > b))  // 降序

case class Person(name: String, age: Int)
val people = List(
  Person("Alice", 25),
  Person("Bob", 20),
  Person("Charlie", 30)
)
println(customSort(people, (a: Person, b: Person) => a.age < b.age))

9.2 返回函数

// 返回函数的函数
def multiplier(factor: Int): Int => Int = {
  (x: Int) => x * factor
}

val triple = multiplier(3)
val double = multiplier(2)

println(triple(5))   // 15
println(double(10))  // 20

// 实用示例:创建验证器
def validator(min: Int, max: Int): Int => Boolean = {
  (x: Int) => x >= min && x <= max
}

val ageValidator = validator(0, 120)
val scoreValidator = validator(0, 100)

println(ageValidator(25))   // true
println(ageValidator(150))  // false
println(scoreValidator(85)) // true
println(scoreValidator(105))// false

9.3 闭包

闭包是引用了外部变量的函数

// 闭包示例
var factor = 3

val multiplier = (x: Int) => x * factor

println(multiplier(10))  // 30

factor = 5
println(multiplier(10))  // 50(factor 改变了)

// 实用示例:计数器
def createCounter(): () => Int = {
  var count = 0
  () => {
    count += 1
    count
  }
}

val counter1 = createCounter()
val counter2 = createCounter()

println(counter1())  // 1
println(counter1())  // 2
println(counter1())  // 3

println(counter2())  // 1(独立的计数器)
println(counter2())  // 2

9.4 柯里化 (Currying)

将多参数函数转换为单参数函数链

// 普通函数
def add(a: Int, b: Int): Int = a + b
println(add(3, 5))  // 8

// 柯里化函数
def addCurried(a: Int)(b: Int): Int = a + b
println(addCurried(3)(5))  // 8

// 部分应用
val add5 = addCurried(5) _
println(add5(10))  // 15
println(add5(3))   // 8

// 实用示例:日志记录
def log(level: String)(message: String): Unit = {
  println(s"[$level] $message")
}

val info = log("INFO") _
val error = log("ERROR") _

info("Application started")   // [INFO] Application started
error("Connection failed")    // [ERROR] Connection failed

// 柯里化用于类型推断
def foldLeft[A, B](list: List[A])(init: B)(f: (B, A) => B): B = {
  list match {
    case Nil => init
    case head :: tail => foldLeft(tail)(f(init, head))(f)
  }
}

val numbers = List(1, 2, 3, 4, 5)
val sum = foldLeft(numbers)(0)(_ + _)
println(sum)  // 15

9.5 常用高阶函数

val numbers = List(1, 2, 3, 4, 5)

// map: 映射转换
println(numbers.map(_ * 2))  // List(2, 4, 6, 8, 10)
println(numbers.map(x => x * x))  // List(1, 4, 9, 16, 25)

// filter: 过滤
println(numbers.filter(_ % 2 == 0))  // List(2, 4)
println(numbers.filter(_ > 3))  // List(4, 5)

// flatMap: 扁平映射
val nested = List(List(1, 2), List(3, 4), List(5))
println(nested.flatMap(x => x))  // List(1, 2, 3, 4, 5)

val words = List("Hello World", "Scala Programming")
println(words.flatMap(_.split(" ")))  // List(Hello, World, Scala, Programming)

// foreach: 遍历(副作用)
numbers.foreach(x => println(x * 2))

// reduce: 归约
println(numbers.reduce(_ + _))  // 15
println(numbers.reduce(_ * _))  // 120
println(numbers.reduce((a, b) => if (a > b) a else b))  // 5(最大值)

// fold: 带初始值的归约
println(numbers.fold(10)(_ + _))  // 25
println(numbers.fold(1)(_ * _))  // 120

// foldLeft / foldRight
println(numbers.foldLeft(0)(_ + _))   // 15
println(numbers.foldRight(0)(_ + _))  // 15

// scan: 累积过程
println(numbers.scanLeft(0)(_ + _))  // List(0, 1, 3, 6, 10, 15)

// zip: 拉链
val letters = List("a", "b", "c", "d", "e")
println(numbers.zip(letters))  // List((1,a), (2,b), (3,c), (4,d), (5,e))

// partition: 分区
val (evens, odds) = numbers.partition(_ % 2 == 0)
println(evens)  // List(2, 4)
println(odds)   // List(1, 3, 5)

// groupBy: 分组
val words2 = List("apple", "banana", "avocado", "cherry", "apricot")
println(words2.groupBy(_.charAt(0)))
// Map(a -> List(apple, avocado, apricot), b -> List(banana), c -> List(cherry))

// take / drop
println(numbers.take(3))  // List(1, 2, 3)
println(numbers.drop(2))  // List(3, 4, 5)

// takeWhile / dropWhile
println(numbers.takeWhile(_ < 4))  // List(1, 2, 3)
println(numbers.dropWhile(_ < 4))  // List(4, 5)

// exists / forall
println(numbers.exists(_ > 3))  // true
println(numbers.forall(_ > 0))  // true

// find: 查找第一个
println(numbers.find(_ > 3))  // Some(4)

// count: 计数
println(numbers.count(_ % 2 == 0))  // 2

10. 隐式转换

10.1 隐式转换函数

自动进行类型转换

// 定义隐式转换
class RichInt(val value: Int) {
  def square: Int = value * value
  def isEven: Boolean = value % 2 == 0
}

// 隐式转换函数
implicit def intToRichInt(x: Int): RichInt = new RichInt(x)

// 使用(Int 自动转换为 RichInt)
println(5.square)  // 25
println(4.isEven)  // true

// 另一个示例:文件操作增强
import java.io.File

class RichFile(val file: File) {
  def read: String = {
    scala.io.Source.fromFile(file).mkString
  }
}

implicit def fileToRichFile(f: File): RichFile = new RichFile(f)

// 使用
// val content = new File("test.txt").read

10.2 隐式参数

自动传递参数

// 定义隐式参数
def greet(name: String)(implicit greeting: String): Unit = {
  println(s"$greeting, $name!")
}

// 定义隐式值
implicit val defaultGreeting: String = "Hello"

// 调用(自动使用隐式值)
greet("Alice")  // Hello, Alice!

// 显式传递(覆盖隐式值)
greet("Bob")("Hi")  // Hi, Bob!

// 实用示例:执行上下文
import scala.concurrent.ExecutionContext

def runAsync(task: => Unit)(implicit ec: ExecutionContext): Unit = {
  // 使用隐式的执行上下文
  println(s"Running on: ${ec.getClass.getSimpleName}")
}

implicit val ec: ExecutionContext = ExecutionContext.global
runAsync {
  println("Async task")
}

10.3 隐式类

为已有类型添加新方法

// 隐式类(必须在 object/class/trait 内)
object Helpers {
  implicit class StringOps(val s: String) {
    def shout: String = s.toUpperCase + "!!!"
    def whisper: String = s.toLowerCase + "..."
  }
  
  implicit class IntOps(val n: Int) {
    def times(f: => Unit): Unit = {
      (1 to n).foreach(_ => f)
    }
  }
}

// 使用
import Helpers._

println("hello".shout)    // HELLO!!!
println("WORLD".whisper)  // world...

// 重复执行
3.times {
  println("Scala!")
}
// 输出3次 Scala!

11. 实用技巧

11.1 Option 类型

优雅处理可能为空的值,避免 NullPointerException

// Option 有两个子类型:Some(有值) 和 None(无值)
val some: Option[Int] = Some(42)
val none: Option[Int] = None

// 获取值
println(some.get)  // 42(不安全,None.get 会抛异常)
println(some.getOrElse(0))  // 42
println(none.getOrElse(0))  // 0

// 判断是否有值
println(some.isDefined)  // true
println(some.isEmpty)    // false
println(none.isDefined)  // false

// map 操作
println(some.map(_ * 2))  // Some(84)
println(none.map(_ * 2))  // None

// flatMap
def divide(a: Int, b: Int): Option[Int] = {
  if (b == 0) None else Some(a / b)
}

println(divide(10, 2))  // Some(5)
println(divide(10, 0))  // None

// for 推导
val result = for {
  a <- Some(10)
  b <- Some(5)
  c <- divide(a, b)
} yield c

println(result)  // Some(2)

// 实用示例:Map 查找
val map = Map("a" -> 1, "b" -> 2)
println(map.get("a"))  // Some(1)
println(map.get("c"))  // None

map.get("a") match {
  case Some(value) => println(s"Found: $value")
  case None => println("Not found")
}

11.2 Try 类型

优雅处理异常

import scala.util.{Try, Su***ess, Failure}

// Try 包装可能抛异常的代码
def divide2(a: Int, b: Int): Try[Int] = Try(a / b)

// 处理结果
divide2(10, 2) match {
  case Su***ess(result) => println(s"Result: $result")
  case Failure(exception) => println(s"Error: ${exception.getMessage}")
}

// 链式调用
val result2 = Try {
  val x = "123".toInt
  val y = "456".toInt
  x + y
}

println(result2)  // Su***ess(579)

val result3 = Try {
  "abc".toInt  // 抛异常
}

println(result3)  // Failure(...)

// map 和 flatMap
val x = Try("42".toInt)
val doubled = x.map(_ * 2)
println(doubled)  // Su***ess(84)

// getOrElse
println(result2.getOrElse(0))  // 579
println(result3.getOrElse(0))  // 0

11.3 偏函数 (Partial Function)

只处理部分输入的函数

// 定义偏函数
val divide: PartialFunction[Int, Int] = {
  case d if d != 0 => 42 / d
}

// 检查是否定义
println(divide.isDefinedAt(2))  // true
println(divide.isDefinedAt(0))  // false

// 使用
println(divide(2))  // 21
// println(divide(0))  // 抛异常

// collect 使用偏函数
val numbers = List(1, 2, 3, 4, 5, 6)

val result = numbers.collect {
  case x if x % 2 == 0 => x * 2
}

println(result)  // List(4, 8, 12)

// 实用示例:消息处理
sealed trait Message
case class TextMessage(text: String) extends Message
case class ImageMessage(url: String) extends Message
case class VideoMessage(url: String, duration: Int) extends Message

val handleText: PartialFunction[Message, String] = {
  case TextMessage(text) => s"Text: $text"
}

val handleImage: PartialFunction[Message, String] = {
  case ImageMessage(url) => s"Image: $url"
}

// 组合偏函数
val handleMessage = handleText orElse handleImage

println(handleMessage(TextMessage("Hello")))  // Text: Hello
println(handleMessage(ImageMessage("pic.jpg")))  // Image: pic.jpg

11.4 lazy 延迟求值

延迟初始化,只在使用时才计算

// 普通变量(立即求值)
val x = {
  println("***puting x")
  42
}
// 立即输出:***puting x

// lazy 变量(延迟求值)
lazy val y = {
  println("***puting y")
  100
}
// 不输出(尚未使用)

println("Using y now")
println(y)  // 第一次使用时才计算
// 输出:***puting y
//      100

println(y)  // 再次使用,不重新计算
// 输出:100

// 实用示例:避免昂贵的初始化
class Resource {
  lazy val connection = {
    println("Opening database connection")
    // 昂贵的连接操作
    "DB Connection"
  }
  
  def query(): Unit = {
    println(s"Querying: $connection")
  }
}

val resource = new Resource()
println("Resource created")
// 不输出 "Opening database connection"

resource.query()
// 输出:Opening database connection
//      Querying: DB Connection

11.5 下划线的多种用法

// 1. 导入所有
import scala.collection.mutable._

// 2. 占位符(Lambda 简写)
List(1, 2, 3).map(_ * 2)
List(1, 2, 3).filter(_ > 2)
List(1, 2, 3).reduce(_ + _)

// 3. 模式匹配中的通配符
val x = 5
x match {
  case 1 => "one"
  case _ => "other"
}

// 4. 忽略变量
val (a, _, c) = (1, 2, 3)  // 忽略第二个元素

// 5. 变长参数展开
val list = List(1, 2, 3)
def sum(nums: Int*) = nums.sum
sum(list: _*)  // 展开为 sum(1, 2, 3)

// 6. 函数转换
def add(a: Int, b: Int) = a + b
val addFunc = add _  // 方法转函数

// 7. 部分应用函数
val add5 = add(5, _: Int)
println(add5(10))  // 15

// 8. 初始化默认值
var map = Map[String, Int]()
map = map.withDefaultValue(0)

11.6 字符串操作技巧

// 判断和检查
val str = "Hello Scala"
println(str.isEmpty)           // false
println(str.nonEmpty)          // true
println(str.contains("Scala")) // true
println(str.startsWith("He"))  // true
println(str.endsWith("la"))    // true

// 分割和连接
val words = str.split(" ")     // Array(Hello, Scala)
val joined = words.mkString("-")  // Hello-Scala

// 去除空白
val text = "  hello  "
println(text.trim)             // "hello"
println(text.stripPrefix("  ")) // "hello  "
println(text.stripSuffix("  ")) // "  hello"

// 替换
println(str.replace("Scala", "World"))  // Hello World
println(str.replaceAll("[aeiou]", "*")) // H*ll* Sc*l*

// 大小写
println(str.toUpperCase)       // HELLO SCALA
println(str.toLowerCase)       // hello scala
println("hello".capitalize)    // Hello

// 格式化
val name = "Alice"
val age = 25
printf("Name: %s, Age: %d%n", name, age)
println(f"$name%-10s is $age%03d years old")

// 多行字符串和 stripMargin
val sql = 
  """SELECT *
    |FROM users
    |WHERE age > 18
    |ORDER BY name""".stripMargin

println(sql)

11.7 集合转换技巧

// Array ↔ List
val arr = Array(1, 2, 3)
val list = arr.toList
val arr2 = list.toArray

// List ↔ Set
val list2 = List(1, 2, 2, 3, 3, 3)
val set = list2.toSet  // Set(1, 2, 3) 自动去重
val list3 = set.toList

// Map ↔ List
val map = Map("a" -> 1, "b" -> 2)
val pairs = map.toList  // List((a,1), (b,2))
val map2 = pairs.toMap

// 元组列表 ↔ 两个列表
val tuples = List((1, "a"), (2, "b"), (3, "c"))
val (nums, chars) = tuples.unzip  // (List(1,2,3), List(a,b,c))

val nums2 = List(1, 2, 3)
val chars2 = List("a", "b", "c")
val zipped = nums2.zip(chars2)  // List((1,a), (2,b), (3,c))

// mkString: 集合转字符串
val list4 = List(1, 2, 3, 4, 5)
println(list4.mkString)           // 12345
println(list4.mkString(", "))     // 1, 2, 3, 4, 5
println(list4.mkString("[", ", ", "]"))  // [1, 2, 3, 4, 5]

11.8 for 推导的高级技巧

// 生成组合
val result1 = for {
  i <- 1 to 3
  j <- 1 to 3
} yield (i, j)
println(result1)
// Vector((1,1), (1,2), (1,3), (2,1), (2,2), (2,3), (3,1), (3,2), (3,3))

// 多重过滤
val result2 = for {
  i <- 1 to 10
  if i % 2 == 0
  if i % 3 == 0
} yield i
println(result2)  // Vector(6)

// 变量绑定
val result3 = for {
  i <- 1 to 5
  square = i * i
  if square > 10
} yield (i, square)
println(result3)  // Vector((4,16), (5,25))

// 嵌套集合展开
val lists = List(List(1, 2), List(3, 4), List(5, 6))
val flattened = for {
  list <- lists
  num <- list
} yield num
println(flattened)  // List(1, 2, 3, 4, 5, 6)

// Option 处理
def safeDivide(a: Int, b: Int): Option[Int] = 
  if (b != 0) Some(a / b) else None

val result4 = for {
  x <- Some(10)
  y <- Some(5)
  z <- safeDivide(x, y)
} yield z
println(result4)  // Some(2)

val result5 = for {
  x <- Some(10)
  y <- Some(0)
  z <- safeDivide(x, y)
} yield z
println(result5)  // None

11.9 常见的函数式编程模式

// 1. 链式调用
val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

val result = numbers
  .filter(_ % 2 == 0)      // 过滤偶数
  .map(_ * 2)              // 乘以2
  .filter(_ > 10)          // 大于10
  .sorted                  // 排序

println(result)  // List(12, 16, 20)

// 2. 函数组合
val addOne = (x: Int) => x + 1
val double = (x: Int) => x * 2
val square = (x: Int) => x * x

val ***posed = addOne andThen double andThen square
println(***posed(5))  // ((5+1)*2)^2 = 144

val ***posed2 = square ***pose double ***pose addOne
println(***posed2(5))  // ((5+1)*2)^2 = 144

// 3. 递归替代循环
def sum(list: List[Int]): Int = list match {
  case Nil => 0
  case head :: tail => head + sum(tail)
}

println(sum(List(1, 2, 3, 4, 5)))  // 15

// 4. 尾递归优化
import scala.annotation.tailrec

@tailrec
def sumTail(list: List[Int], a***: Int = 0): Int = list match {
  case Nil => a***
  case head :: tail => sumTail(tail, a*** + head)
}

println(sumTail(List(1, 2, 3, 4, 5)))  // 15

// 5. 柯里化应用
def calculate(operator: String)(a: Int, b: Int): Int = operator match {
  case "+" => a + b
  case "-" => a - b
  case "*" => a * b
  case "/" => a / b
}

val add = calculate("+") _
val multiply = calculate("*") _

println(add(10, 5))       // 15
println(multiply(10, 5))  // 50

11.10 实用工具方法

// 计时工具
def time[T](block: => T): T = {
  val start = System.currentTimeMillis()
  val result = block
  val end = System.currentTimeMillis()
  println(s"Time: ${end - start} ms")
  result
}

// 使用
time {
  (1 to 1000000).sum
}

// 重试工具
import scala.util.{Try, Su***ess, Failure}

def retry[T](n: Int)(fn: => T): Try[T] = {
  Try(fn) match {
    case Su***ess(x) => Su***ess(x)
    case Failure(e) if n > 1 => 
      println(s"Retry... ($n attempts left)")
      retry(n - 1)(fn)
    case Failure(e) => Failure(e)
  }
}

// 使用
var counter = 0
val result = retry(3) {
  counter += 1
  if (counter < 3) throw new Exception("Failed")
  else "Su***ess"
}

println(result)  // Su***ess(Su***ess)

// 缓存工具(记忆化)
def memoize[A, B](f: A => B): A => B = {
  val cache = scala.collection.mutable.Map[A, B]()
  (a: A) => cache.getOrElseUpdate(a, f(a))
}

// 使用(斐波那契)
lazy val fib: Int => BigInt = memoize {
  case 0 => 0
  case 1 => 1
  case n => fib(n - 1) + fib(n - 2)
}

println(fib(100))  // 很快得出结果

11.11 常见陷阱和注意事项

// 1. == 和 eq 的区别
val s1 = "hello"
val s2 = "hello"
val s3 = new String("hello")

println(s1 == s2)   // true  (比较内容)
println(s1 eq s2)   // true  (比较引用)
println(s1 == s3)   // true  (比较内容)
println(s1 eq s3)   // false (不同对象)

// 2. 可变集合 vs 不可变集合
import scala.collection.mutable

// 不可变(默认)
val list1 = List(1, 2, 3)
// list1 += 4  // 错误!

// 可变
val list2 = mutable.ListBuffer(1, 2, 3)
list2 += 4  // OK

// 3. return 的陷阱
def findFirst(list: List[Int], target: Int): Option[Int] = {
  list.foreach { x =>
    if (x == target) return Some(x)  // ⚠️ 不推荐
  }
  None
}

// 推荐写法(函数式)
def findFirst2(list: List[Int], target: Int): Option[Int] = {
  list.find(_ == target)
}

// 4. 空集合的处理
val empty = List[Int]()
// println(empty.head)  // 抛异常!
println(empty.headOption)  // None(安全)

// 5. 类型擦除
def isIntList(x: Any): Boolean = x match {
  case _: List[Int] => true  // ⚠️ 类型擦除,实际匹配任何 List
  case _ => false
}

println(isIntList(List(1, 2, 3)))      // true
println(isIntList(List("a", "b", "c")))// true(也是 true!)

// 6. 惰性求值的副作用
var x = 0
lazy val y = { x += 1; x }

println(x)  // 0
println(y)  // 1(第一次求值)
println(x)  // 1
println(y)  // 1(不再重新计算)
println(x)  // 1

12. 实战综合案例

12.1 文件读写

import scala.io.Source
import java.io.{File, PrintWriter}

// 读取文件
def readFile(filename: String): List[String] = {
  val source = Source.fromFile(filename)
  try {
    source.getLines().toList
  } finally {
    source.close()
  }
}

// 写入文件
def writeFile(filename: String, lines: List[String]): Unit = {
  val writer = new PrintWriter(new File(filename))
  try {
    lines.foreach(writer.println)
  } finally {
    writer.close()
  }
}

// 使用
val lines = List("Line 1", "Line 2", "Line 3")
writeFile("output.txt", lines)
val content = readFile("output.txt")
println(content)

12.2 JSON 处理(伪代码示例)

// 使用 play-json 库
import play.api.libs.json._

// 定义样例类
case class Person(name: String, age: Int, email: String)

// 定义 JSON 格式化器
implicit val personFormat: Format[Person] = Json.format[Person]

// 对象 → JSON
val person = Person("Alice", 25, "alice@example.***")
val json = Json.toJson(person)
println(json)
// {"name":"Alice","age":25,"email":"alice@example.***"}

// JSON → 对象
val jsonStr = """{"name":"Bob","age":30,"email":"bob@example.***"}"""
val personObj = Json.parse(jsonStr).as[Person]
println(personObj)  // Person(Bob,30,bob@example.***)

12.3 简单的学生管理系统

// 定义数据模型
case class Student(id: Int, name: String, age: Int, grade: Double)

class StudentManager {
  private var students = List[Student]()
  
  // 添加学生
  def addStudent(student: Student): Unit = {
    students = students :+ student
    println(s"Added: ${student.name}")
  }
  
  // 删除学生
  def removeStudent(id: Int): Unit = {
    students = students.filterNot(_.id == id)
    println(s"Removed student with ID: $id")
  }
  
  // 查找学生
  def findStudent(id: Int): Option[Student] = {
    students.find(_.id == id)
  }
  
  // 列出所有学生
  def listAll(): Unit = {
    students.foreach(println)
  }
  
  // 按成绩排序
  def sortByGrade(): List[Student] = {
    students.sortBy(_.grade).reverse
  }
  
  // 统计平均分
  def averageGrade(): Double = {
    if (students.isEmpty) 0.0
    else students.map(_.grade).sum / students.length
  }
  
  // 查找优秀学生(>= 90)
  def excellentStudents(): List[Student] = {
    students.filter(_.grade >= 90)
  }
}

// 使用示例
val manager = new StudentManager()

manager.addStudent(Student(1, "Alice", 20, 95.5))
manager.addStudent(Student(2, "Bob", 21, 88.0))
manager.addStudent(Student(3, "Charlie", 19, 92.5))
manager.addStudent(Student(4, "David", 22, 78.0))

println("\n所有学生:")
manager.listAll()

println("\n按成绩排序:")
manager.sortByGrade().foreach(println)

println(f"\n平均分: ${manager.averageGrade()}%.2f")

println("\n优秀学生:")
manager.excellentStudents().foreach(println)

println("\n查找学生 ID=2:")
manager.findStudent(2) match {
  case Some(student) => println(student)
  case None => println("Not found")
}

manager.removeStudent(2)

println("\n删除后的所有学生:")
manager.listAll()

12.4 词频统计程序

object WordCount {
  def countWords(text: String): Map[String, Int] = {
    text
      .toLowerCase                    // 转小写
      .split("\\W+")                 // 分词
      .filter(_.nonEmpty)            // 过滤空字符串
      .groupBy(identity)             // 按单词分组
      .mapValues(_.length)           // 计数
  }
  
  def topN(wordCount: Map[String, Int], n: Int): List[(String, Int)] = {
    wordCount.toList
      .sortBy(-_._2)                 // 按频率降序
      .take(n)                       // 取前 N 个
  }
  
  def main(args: Array[String]): Unit = {
    val text = """
      Scala is a powerful language.
      Scala ***bines object-oriented and functional programming.
      Scala runs on the JVM.
      Scala is scalable from small scripts to large systems.
    """
    
    val wordCount = countWords(text)
    
    println("词频统计:")
    wordCount.foreach { case (word, count) =>
      println(f"$word%-15s: $count")
    }
    
    println("\nTop 5 词:")
    topN(wordCount, 5).foreach { case (word, count) =>
      println(f"$word%-15s: $count")
    }
  }
}

12.5 简单的 HTTP 服务器(使用 Akka HTTP 概念示例)

// 伪代码示例(展示概念)
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route

object SimpleWebServer {
  // 定义路由
  val route: Route = {
    path("hello") {
      get {
        ***plete("Hello, Scala!")
      }
    } ~
    path("user" / IntNumber) { userId =>
      get {
        ***plete(s"User ID: $userId")
      }
    } ~
    path("api" / "users") {
      post {
        entity(as[String]) { userData =>
          ***plete(s"Created user: $userData")
        }
      }
    }
  }
  
  // 启动服务器
  def main(args: Array[String]): Unit = {
    // Http().newServerAt("localhost", 8080).bind(route)
    println("Server started at http://localhost:8080")
  }
}

13. 学习路线建议

初级阶段(1-2周)

  1. ✅ 掌握基本语法(变量、类型、运算符)
  2. ✅ 理解流程控制(if、for、while)
  3. ✅ 学习函数定义和调用
  4. ✅ 熟悉基本集合操作(List、Array、Map)

中级阶段(2-4周)

  1. ✅ 掌握面向对象(类、继承、特质)
  2. ✅ 学习样例类和模式匹配
  3. ✅ 理解高阶函数(map、filter、reduce)
  4. ✅ 学习 Option、Try 等函数式特性

高级阶段(1-2月)

  1. ✅ 掌握隐式转换
  2. ✅ 学习函数式编程模式
  3. ✅ 了解并发编程(Future、Actor)
  4. ✅ 实战项目练习

14. 常用资源

官方文档

  • 📖 Scala 官网: https://www.scala-lang.org/
  • 📖 Scala 文档: https://docs.scala-lang.org/
  • 📖 Scala API: https://www.scala-lang.org/api/current/

推荐书籍

  • 📚 《Scala 编程》(Programming in Scala)
  • 📚 《Scala 函数式编程》(Functional Programming in Scala)
  • 📚 《Scala 实用指南》(Pragmatic Scala)

在线练习

  • 💻 Scala Exercises: https://www.scala-exercises.org/
  • 💻 Leetcode: 支持 Scala 提交

15. 总结

Scala 核心特性

  1. 🔥 多范式: OOP + FP
  2. 类型安全: 强类型 + 类型推断
  3. 📦 表达力强: 简洁优雅
  4. 🌐 JVM 互操作: 无缝调用 Java

学习建议

  • 💡 从函数式思维开始
  • 💡 多练习集合操作
  • 💡 理解不可变性
  • 💡 活用模式匹配
  • 💡 结合实战项目

最佳实践

  • ✅ 优先使用 val 而非 var
  • ✅ 优先使用不可变集合
  • ✅ 善用 Option 避免 null
  • ✅ 使用 case class 建模数据
  • ✅ 链式调用函数而非循环
  • ✅ 利用模式匹配简化逻辑
转载请说明出处内容投诉
CSS教程网 » Scala 从入门到精通学习笔记

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买