模式匹配
This commit is contained in:
		
							
								
								
									
										16
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								README.md
									
									
									
									
									
								
							| @@ -141,13 +141,25 @@ TODO | ||||
| ## 十二、Scala | ||||
|  | ||||
| 1. [Scala简介及开发环境配置](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala简介及开发环境配置.md) | ||||
|  | ||||
| 2. [基本数据类型和运算符](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala基本数据类型和运算符.md) | ||||
|  | ||||
| 3. [流程控制语句](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala流程控制语句.md) | ||||
|  | ||||
| 4. [数组——Array](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala数组.md) | ||||
|  | ||||
| 5. [集合类型综述](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala集合类型.md) | ||||
|  | ||||
| 6. [常用集合类型之——List & Set](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala列表和集.md) | ||||
|  | ||||
| 7. [常用集合类型之——Map & Tuple](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala映射和元组.md) | ||||
| 8. [Scala类和对象](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala类和对象.md) | ||||
| 9. [Scala继承和特质](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala继承和特质.md) | ||||
|  | ||||
| 8. [类和对象](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala类和对象.md) | ||||
|  | ||||
| 9. [继承和特质](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala继承和特质.md) | ||||
|  | ||||
| 10. [函数和闭包](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala函数和闭包.md) | ||||
|  | ||||
| 11. [模式匹配](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Scala模式匹配.md) | ||||
|  | ||||
|      | ||||
| @@ -71,17 +71,19 @@ object ScalaApp extends App { | ||||
| } | ||||
| ``` | ||||
|  | ||||
| 匿名函数: | ||||
| 在Scala中你不必给每一个函数都命名,如`(x: Int) => 3 * x`就是一个匿名函数: | ||||
|  | ||||
| ```scala | ||||
| object ScalaApp extends App { | ||||
|   // 1.将匿名函数赋值给变量fun | ||||
|   // 1.匿名函数 | ||||
|   (x: Int) => 3 * x | ||||
|   // 2.具名函数 | ||||
|   val fun = (x: Int) => 3 * x | ||||
|   // 2.直接使用匿名函数 | ||||
|   // 3.直接使用匿名函数 | ||||
|   val array01 = Array(1, 2, 3).map((x: Int) => 3 * x)   | ||||
|   // 3.使用占位符简写匿名函数 | ||||
|   // 4.使用占位符简写匿名函数 | ||||
|   val array02 = Array(1, 2, 3).map(_ * 3) | ||||
|   // 4.使用匿名函数变量 | ||||
|   // 5.使用具名函数 | ||||
|   val array03 = Array(1, 2, 3).map(fun) | ||||
|    | ||||
| } | ||||
| @@ -91,7 +93,7 @@ object ScalaApp extends App { | ||||
|  | ||||
| #### 1. 可变长度参数列表 | ||||
|  | ||||
| 在java中如果你想要传递可变长度的参数列表,则需要使用`String ...args`这种语法,Scala中等效的语法为`args: String*`。 | ||||
| 在Java中如果你想要传递可变长度的参数列表,则需要使用`String ...args`这种语法,Scala中等效的语法为`args: String*`。 | ||||
|  | ||||
| ```scala | ||||
| object ScalaApp extends App { | ||||
|   | ||||
							
								
								
									
										177
									
								
								notes/Scala模式匹配.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								notes/Scala模式匹配.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,177 @@ | ||||
| # Scala模式匹配 | ||||
|  | ||||
| <nav> | ||||
| <a href="#一模式匹配">一、模式匹配</a><br/> | ||||
|         <a href="#11-更好的swith">1.1 更好的swith</a><br/> | ||||
|         <a href="#12-用作类型检查">1.2 用作类型检查</a><br/> | ||||
|         <a href="#13-匹配数据结构">1.3 匹配数据结构</a><br/> | ||||
|         <a href="#14-提取器">1.4 提取器</a><br/> | ||||
| <a href="#二样例类">二、样例类</a><br/> | ||||
|         <a href="#21-样例类">2.1 样例类</a><br/> | ||||
|         <a href="#23-用于模式匹配">2.3 用于模式匹配</a><br/> | ||||
| </nav> | ||||
|  | ||||
| ## 一、模式匹配 | ||||
|  | ||||
| Scala支持模式匹配机制,可以代替swith语句、执行类型检查、以及支持析构表达式等。 | ||||
|  | ||||
| ### 1.1 更好的swith | ||||
|  | ||||
| Scala不支持swith,可以使用模式匹配`match...case`语法代替。但是match语句与Java中的switch有以下三点不同: | ||||
|  | ||||
| - Scala中的case语句支持任何类型;而Java中case语句仅支持整型、枚举和字符串常量; | ||||
| - Scala中每个分支语句后面不需要写break,因为在case语句中break是隐含的,默认就有; | ||||
| - 在Scala中match语句是有返回值的,而Java中switch语句是没有返回值的。如下: | ||||
|  | ||||
| ```scala | ||||
| object ScalaApp extends App { | ||||
|  | ||||
|   def matchTest(x: Int) = x match { | ||||
|     case 1 => "one" | ||||
|     case 2 => "two" | ||||
|     case _ if x > 9 && x < 100 => "两位数"   //支持条件表达式 这被称为模式守卫 | ||||
|     case _ => "other" | ||||
|   } | ||||
|  | ||||
|   println(matchTest(1))   //输出 one | ||||
|   println(matchTest(10))  //输出 两位数 | ||||
|   println(matchTest(200)) //输出 other | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ### 1.2 用作类型检查 | ||||
|  | ||||
| ```scala | ||||
| object ScalaApp extends App { | ||||
|  | ||||
|   def matchTest[T](x: T) = x match { | ||||
|     case x: Int => "数值型" | ||||
|     case x: String => "字符型" | ||||
|     case x: Float => "浮点型" | ||||
|     case _ => "other" | ||||
|   } | ||||
|  | ||||
|   println(matchTest(1))     //输出 数值型 | ||||
|   println(matchTest(10.3f)) //输出 浮点型 | ||||
|   println(matchTest("str")) //输出 字符型 | ||||
|   println(matchTest(2.1))   //输出 other | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ### 1.3 匹配数据结构 | ||||
|  | ||||
| 匹配元组示例: | ||||
|  | ||||
| ```scala | ||||
| object ScalaApp extends App { | ||||
|  | ||||
|   def matchTest(x: Any) = x match { | ||||
|     case (0, _, _) => "匹配第一个元素为0的元组" | ||||
|     case (a, b, c) => println(a + "~" + b + "~" + c) | ||||
|     case _ => "other" | ||||
|   } | ||||
|  | ||||
|   println(matchTest((0, 1, 2)))             // 输出: 匹配第一个元素为0的元组 | ||||
|   matchTest((1, 2, 3))                      // 输出: 1~2~3 | ||||
|   println(matchTest(Array(10, 11, 12, 14))) // 输出: other | ||||
| } | ||||
| ``` | ||||
|  | ||||
| 匹配数组示例: | ||||
|  | ||||
| ```scala | ||||
| object ScalaApp extends App { | ||||
|  | ||||
|   def matchTest[T](x: Array[T]) = x match { | ||||
|     case Array(0) => "匹配只有一个元素0的数组" | ||||
|     case Array(a, b) => println(a + "~" + b) | ||||
|     case Array(10, _*) => "第一个元素为10的数组" | ||||
|     case _ => "other" | ||||
|   } | ||||
|  | ||||
|   println(matchTest(Array(0)))          // 输出: 匹配只有一个元素0的数组 | ||||
|   matchTest(Array(1, 2))                // 输出: 1~2 | ||||
|   println(matchTest(Array(10, 11, 12))) // 输出: 第一个元素为10的数组 | ||||
|   println(matchTest(Array(3, 2, 1)))    // 输出: other | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ### 1.4 提取器 | ||||
|  | ||||
| 数组、列表和元组能使用模式匹配,都是依靠提取器(extractor)机制,它们伴生对象中定义unapply或unapplySeq方法: | ||||
|  | ||||
| + unapply方法用于提取固定数量的对象; | ||||
| + unapplySeq用于提取一个序列; | ||||
|  | ||||
| 以下是`Array.scala`类源码中定义的`unapplySeq`方法: | ||||
|  | ||||
| ```scala | ||||
| def unapplySeq[T](x : scala.Array[T]) : scala.Option[scala.IndexedSeq[T]] = { /* compiled code */ } | ||||
| ``` | ||||
|  | ||||
| `unapplySeq`返回一个序列值,即数组中的值,以和模式匹配case语句中的表达式进行对应位置的值匹配。 | ||||
|  | ||||
|  | ||||
|  | ||||
| ## 二、样例类 | ||||
|  | ||||
| ### 2.1 样例类 | ||||
|  | ||||
| 样例类是一种的特殊的类,它们被经过优化以用于模式匹配,样例类的声明比较简单,只需要在`class`前面加上关键字`case`。下面给出一个样例类及其用于模式匹配的示例: | ||||
|  | ||||
| ```scala | ||||
| //声明一个抽象类 | ||||
| abstract class Person{ | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```scala | ||||
| // 样例类Employee | ||||
| case class Employee(name: String, age: Int, salary: Double) extends Person { | ||||
|  | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```scala | ||||
| // 样例类Student | ||||
| case class Student(name: String, age: Int) extends Person { | ||||
|  | ||||
| } | ||||
| ``` | ||||
|  | ||||
| 当你声明样例类后,编译器自动进行以下配置: | ||||
|  | ||||
| - 构造器中每个参数都默认为`val`; | ||||
| - 自动地生成`equals, hashCode, toString, copy`等方法; | ||||
| - 伴生对象中自动生成`apply`方法,使得不用new关键字就能构造出相应的对象; | ||||
| - 伴生对象中自动生成`unapply`方法,以支持模式匹配。 | ||||
|  | ||||
| 除了上面的特征外,样例类和其他类相同,可以任意添加方法和字段,扩展它们。 | ||||
|  | ||||
| ### 2.3 用于模式匹配 | ||||
|  | ||||
| 样例的伴生对象中自动生成`unapply`方法,所以样例类可以支持模式匹配,使用如下: | ||||
|  | ||||
| ```scala | ||||
| object ScalaApp extends App { | ||||
|  | ||||
|   def matchTest(person: Person) = person match { | ||||
|     case Student(name, _) => "student:" + name | ||||
|     case Employee(_, _, salary) => "employee salary:" + salary | ||||
|     case _ => "other" | ||||
|   } | ||||
|  | ||||
|   println(matchTest(Student("heibai", 12)))        //输出: student:heibai | ||||
|   println(matchTest(Employee("ying", 22, 999999))) //输出: employee salary:999999.0 | ||||
| } | ||||
| ``` | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ## 参考资料 | ||||
|  | ||||
| 1. Martin Odersky . Scala编程(第3版)[M] . 电子工业出版社 . 2018-1-1   | ||||
| 2. 凯.S.霍斯特曼  . 快学Scala(第2版)[M] . 电子工业出版社 . 2017-7 | ||||
|  | ||||
| @@ -1,5 +1,6 @@ | ||||
| # 流程控制语句 | ||||
|  | ||||
|  | ||||
| <nav> | ||||
| <a href="#一条件表达式if">一、条件表达式if</a><br/> | ||||
| <a href="#二块表达式">二、块表达式</a><br/> | ||||
| <a href="#三循环表达式while">三、循环表达式while</a><br/> | ||||
| @@ -161,7 +162,7 @@ object ScalaApp extends App { | ||||
|  | ||||
| 但是与Java中的switch有以下三点不同: | ||||
|  | ||||
|  | ||||
| + Scala中的case语句支持任何类型;而Java中case语句仅支持整型、枚举和字符串常量; | ||||
| + Scala中每个分支语句后面不需要写break,因为在case语句中break是隐含的,默认就有; | ||||
| + 在Scala中match语句是有返回值的,而Java中switch语句是没有返回值的。如下: | ||||
|  | ||||
|   | ||||
							
								
								
									
										0
									
								
								notes/Scala类型参数化.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								notes/Scala类型参数化.md
									
									
									
									
									
										Normal file
									
								
							
		Reference in New Issue
	
	Block a user