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周)
- ✅ 掌握基本语法(变量、类型、运算符)
- ✅ 理解流程控制(if、for、while)
- ✅ 学习函数定义和调用
- ✅ 熟悉基本集合操作(List、Array、Map)
中级阶段(2-4周)
- ✅ 掌握面向对象(类、继承、特质)
- ✅ 学习样例类和模式匹配
- ✅ 理解高阶函数(map、filter、reduce)
- ✅ 学习 Option、Try 等函数式特性
高级阶段(1-2月)
- ✅ 掌握隐式转换
- ✅ 学习函数式编程模式
- ✅ 了解并发编程(Future、Actor)
- ✅ 实战项目练习
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 核心特性
- 🔥 多范式: OOP + FP
- ⚡ 类型安全: 强类型 + 类型推断
- 📦 表达力强: 简洁优雅
- 🌐 JVM 互操作: 无缝调用 Java
学习建议
- 💡 从函数式思维开始
- 💡 多练习集合操作
- 💡 理解不可变性
- 💡 活用模式匹配
- 💡 结合实战项目
最佳实践
- ✅ 优先使用
val而非var - ✅ 优先使用不可变集合
- ✅ 善用
Option避免 null - ✅ 使用
case class建模数据 - ✅ 链式调用函数而非循环
- ✅ 利用模式匹配简化逻辑