scala模式匹配

1.模式匹配

1.1简单模式匹配

1
2
3
4
5
6
7
8
9
10
// 简单模式匹配
print("请输入一个字符串:")
// val UserStdIn: Any = StdIn.readLine()
val UserStdIn: Any = "hadoop"
UserStdIn match {
case "hadoop" => println("你真是个天才")
case "flume" => println("你也是个天才")
case "flink" => println("人才")
case _ => println("默认项")
}

1.2匹配类型

1
2
3
4
5
6
7
// 匹配类型
UserStdIn match {
case _: String => println("这是一个字符串")
case _: Int => println("这是一个整形")
case _: Char => println("这是一个字符")
case _ => println("默认项")
}

1.3守卫

1
2
3
4
5
6
7
8
// 守卫 所谓的守卫指的是在case语句中添加if条件判断,这样可以让我们的代码更简洁,更优雅
// val NumStdin = StdIn.readInt()
val NumStdin = 22
NumStdin match {
case x if (x % 2 == 0) => println("是个偶数")
case x if (x == 0) => println("是零")
case _ => println("是别的数字")
}

1.4匹配样例类

1
2
3
4
5
6
7
8
9
// 匹配样例类  可以快速拿到传入类的参数
val c: Any = Customer("张三", 23)
val o: Any = Order(1)

c match {
case Customer(name, age) => println(s"Customer类型的对象, name=${name}, age=${age}")
case Order(id) => println(s"Order类型的对象, id=${id}")
case _ => println("未匹配")
}

1.5匹配数组、元祖、集合、列表、映射、集

1
2
3
4
5
6
7
8
9
10
11
// 匹配数组、元祖、集合、列表、映射、集
val arr1 = Array(1, 4, 9)
val arr2 = Array(0)
val arr3 = Array(0, 1, 4, 5)

arr1 match {
case Array(1, x, y) => println(s"匹配到数组:长度为3,首元素为1,剩下两个元素无所谓,这里剩下的两个元素分别是:${x}, ${y}")
case Array(0) => println("匹配到数组:长度为1,且只有一个元素0")
case Array(0, _*) => println("匹配到数组:以元素0开头,后边的元素无所谓")
case _ => println("未匹配")
}

1.6匹配列表

1
2
3
4
5
6
7
8
9
10
11
// 匹配列表
val list1 = List(0)
val list2 = (0 to 100).toList
val list3 = List(2, 4)

list1 match {
case 0 :: Nil => println("只包含一个0")
case 0 :: tail => println("以0开头的列表,数量不固定")
case x :: y :: Nil => println(s"只有两个数字的列表,数字分别是: ${x}, ${y}")
case _ => println("不匹配")
}

1.7匹配元组

1
2
3
4
5
6
7
8
9
10
// 匹配元祖
val tuple1 = (1, 2, 3)
val tuple2 = (3, 4, 5)
val tuple3 = (3, 4)

tuple1 match {
case (1, x, y) => println(s"以1开头的元祖,一共三个元素,另外两个元素为${x}, ${y}")
case (x, y, 5) => println("一共三个元素,最后一个元素为5的元祖")
case _ => println("不匹配")
}

1.8变量生命中的模式匹配

1
2
3
4
5
6
7
8
9
// 变量声明中的模式匹配
val arr4 = (0 to 10).toArray
// 获得第二个,第三个,第四个元素
val Array(_, x, y, z, _*) = arr4
println(x, y, z)
// 获得第一个,第二个元素
val list5 = (0 to 10).toList
val List(a, b, _*) = list5
println(a, b)

1.9匹配for表达式

1
2
3
4
5
6
// 匹配for表达式
val map1 = Map("张三" -> 13, "李四" -> 34, "王五" -> 34, "赵柳" -> 44)
// 方式1
for ((k, v) <- map1 if (v == 34)) println(k, v)
// 方式2
for ((k, 34) <- map1) println(k, 34)

2.Option类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def divide(a: Int, b: Int)= {
if (b == 0) None
else Some(a / b)
}

// 思路一
val result1 = divide(10, 0)
println(result1)
// 思路二
result1 match {
case Some(x) => println(x)
case None => println("不能为0")
}
// 思路三
println(result1.getOrElse("不能为0"))

3.偏函数

1
2
3
4
5
6
7
8
9
10
// 偏函数
val pf: PartialFunction[Int, String] = {
case 1 => "一"
case 2 => "二"
case 3 => "三"
case 4 => "四"
case _ => "未匹配"
}
println(pf(1))
println(pf(2))

3.1结合map函数使用偏函数

1
2
3
4
5
6
7
8
9
// 结合map函数使用偏函数
val list11 = (1 to 10).toList
//核心: 偏函数 结合 集合的函数式编程来使用
val list12 = list11.map {
case x if x >= 1 && x <= 3 => "[1-3]"
case x if x >= 4 && x <= 8 => "[4-8]"
case _ => "(8-*]"
}
println(list12)

3.2正则表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 正则表达式
val email = "hkjcpdd123@163.com"
val regex = """.+@.+\..+""".r
if (regex.findAllMatchIn(email).nonEmpty) { // 那个nonEmpty就是i.size != 0
// 能走到这里, 说明是合法邮箱
println(s"${email}是合法的邮箱")
} else {
// 走到这里,说明是非法的邮箱
println(s"${email}是合法的邮箱")
}

// 正则2:过滤所有不合法的邮箱
val list14 = List("123456789@qq.com", "a1da7897689@gmail.com", "123afaadd.com")
val regex1 = """.+@.+\..+""".r
val filterList = list14.filter(regex1.findAllMatchIn(_).nonEmpty)
println(filterList)
// 正则3:获取邮箱运营商
val list15 = List("hkjcpdd@qq.com", "hkjmjj@gmail.com", "zhangsan@163.com", "123foshana.com")
val regex2 = """.+@(.+)\..+""".r
val filterList1 = list15.map {
//固定格式 表示要校验的邮箱,固定格式 正则对象(对应的是正则中的分组内容) 固定格式 邮箱->运营商
// 这里@是匹配的意思,就是后者正则匹配成功的就赋值给x
case x@regex2(company) => x -> company
case x => x -> "未匹配"
}
println(filterList1)

4.异常处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 异常处理
// 方式一:补货异常
try {
// 可能出现问题的代码
// val i = 10 / 0
val i = 10 / 1
} catch {
// 出现问题后的解决方案
// case ex:ArithmeticException => println("算术异常")
case ex: Exception => ex.printStackTrace()
} finally {
// 这里一般用来释放资源的
println("我是用来释放资源的")
}
// 方式二:抛出异常
// throw new Exception("我是一个异常")

5.提取器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 提取器
// 方式1 普通写法
val s1 = new Student("张三", 23)
// 方式2 免new
val s2 = Student("李四", 23)
// 获取对象中的各个属性值,然后打印
// 方式1 普通获取
println(s1.name, s1.age, s2.name, s2.age)
// 方式2 直接调用unapply方法
Student.unapply(s1)
// 方式3 通过模式匹配获取
s1 match {
case Student(name, age) => println(name, age)
case _ => println("未匹配")
}

6.案例:随机职业

1
2
3
4
5
6
7
8
9
10
11
12
13
// 随机职业
// 1.提示用户录入整数,匹配对应的职业
println("请录入一个整数1~5, 我来告诉你上辈子的职业:")
val num = StdIn.readInt()
val occupation = num match {
case 1 => "人机"
case 1 => "人才"
case 1 => "黄凯君"
case 1 => "黄开俊"
case 1 => "黄凯军"
case _ => "未匹配"
}
println(occupation)