def main(args: Array[String]): Unit ={
val v ="/"
v match{case"+"=>println("++++++++++++")case"-"=>println("------------")}}
Exception in thread "main" scala.MatchError:/(of classjava.lang.String)
at com.nefu.scala.chaptor08.Scala01_Match1$.main(Scala01_Match1.scala:11)
at com.nefu.scala.chaptor08.Scala01_Match1.main(Scala01_Match1.scala)
每个 case 中,不用 break 语句。
可以在 match 中使用任何类型,而不仅仅是数字。
Jav的switch语句支持的类型:
byteshortintcharenum String
// Javaint i =1;switch( i ){case0:break;case1:break;default:break}
下面是Scala:
变量 match {case _:1//默认可以放在最上面case ex:Exception =>println(ex.getMessage)}
异常处理中的模式匹配:
try{
val r =10/0//0不能作为除数}catch{case ex: ArithmeticException=>println("捕获了除数为零的算数异常")case ex: Exception =>println("捕获了异常")}finally{// 无论有没有出现异常都要执行的代码}}
2 守卫
如果想要表达匹配某个范围的数据,就需要在模式匹配中增加条件守卫 守卫条件更灵活 增加了一个条件判断
val v ="a"
v match {case"+"=>println("++++++++++++")case"-"=>println("------------")case _ if(v.equals("a"))=>println("aaaaaaaaaaaaa")case _ =>println("Nothing...")}
3 模式中的变量
如果在 case 关键字后跟变量名,那么 match 前表达式的值会赋给那个变量。
val v ="a"
v match {case"+"=>println("++++++++++++")case"-"=>println("------------")case ch =>println("length = "+ ch.length)case _ if(v.equals("a"))=>println("aaaaaaaaaaaaa")case _ =>println("Nothing...")
val a =6
val obj =if(a ==1)1elseif(a ==2)"2"elseif(a ==3)BigInt(3)elseif(a ==4)Map("aa"->1)elseif(a ==5)Map(1->"aa")elseif(a ==6)Array(1,2,3)elseif(a ==7)Array("aa",1)elseif(a ==8)Array("aa")//在类型的模式匹配中不支持泛型 Map[String, Int]和Map[Int, String]一样
val r1 = obj match {case x: Int => x //类型匹配case s: String => s.toInt
case _: BigInt => Int.MaxValue //这个下划线是变量名 ???case m: Map[String, Int]=>"Map[String, Int]类型的 Map 集合"case m: Map[Int, String]=>"Map[Int,String]类型的 Map 集合"case a: Array[String]=>"It's an Array[String]"//String[]case a: Array[Int]=>"It's an Array[Int]"//int[]case _ =>0}println(r1 +", "+ r1.getClass.getName
length =1
It's an Array[Int], java.lang.String
注: 类型不能直接匹配泛型类型(类型匹配不考虑泛型) 数组的“泛型”其实是类型,所以生效。
5 匹配数组、列表、元组
Array(0) 匹配只有一个元素且为 0 的数组。
Array(x,y) 匹配数组有两个元素,并将两个元素赋值为 x 和 y。
Array(0,_*) 匹配数组以 0 开始。
5.1 匹配数组
for(arr <-Array(Array(0),Array(1,0),Array(0,1,0),Array(1,1,0),Array(1,1,0,1))){
val result = arr match {caseArray(0)=>"0"caseArray(x, y)=> x +" "+ y
caseArray(x, y, z)=> x +" "+ y +" "+ z
caseArray(0, _*)=>"0..."case _ =>"something else"}println(result)
010010110
something else
5.2 匹配列表
与匹配数组相似,同样可以应用于列表
for(list <-Array(List(0),List(1,0),List(0,0,0),List(1,0,0))){
val result = list match {case0:: Nil =>"0"case x :: y :: Nil => x +" "+ y //(1, 0)case0:: tail =>"0 ..."//list(0)上面已经满足了case _ =>"something else"}println(result)}
0100...
something else
5.3 匹配元组
同样可以应用于元组
for(pair <-Array((0,1),(1,0),(1,1))){
val result = pair match {case(0, _)=>"0 ..."case(y,0)=> y +" 0"case _ =>"neither is 0"}println(result)}
0...10
neither is 0
6 对象匹配
对象匹配,什么才算是匹配呢?即, case 中对象的 unapply 方法返回 some 集合则为匹配成功,返回 none 集合则为匹配失败。
6.1 unapply
调用 unapply,传入 number
接收返回值并判断返回值是 None,还是 Some
如果是 Some,则将其中的值赋值给 n(就是 case Square(n)中的 n)
请参考伴生对象的 apply 方法理解
object Square {
def unapply(z: Double): Option[Double]={Some(math.sqrt(z))}}//unapply 提取器
val number: Double =36.0
number match {caseSquare(n)=>println(n)case _ =>println("nothing matched")}
for(amt <-Array(Dollar(1000.0),Currency(1000.0,"EUR"), Nothing)){
val result = amt match {caseDollar(v)=>"$"+ v
caseCurrency(_, u)=> u
case Nothing =>""}println(amt +": "+ result)}
当你声明样例类时,如下几件事情会自动发生:
构造器中的每一个参数都成为 val——除非它被显式地声明为 var(不建议这样做)
在伴生对象中提供 apply 方法让你不用 new 关键字就能构造出相应的对象,比如Dollar(29.95)或 Currency(29.95, "EUR")
abstractclassTrafficLightColorcase object Red extendsTrafficLightColorcase object Yellow extendsTrafficLightColorcase object Green extendsTrafficLightColor
13.2 模拟枚举
for(color <-Array(Red, Yellow, Green))println(
color match {case Red =>"stop"case Yellow =>"slowly"case Green =>"go"})
14 偏函数
将集合中的数字加 1 并返回新的集合
val list =List(1,2,3,4)
def add( obj : Any ): Int ={
obj match {case i:Int => i+1}}
val list1 = list.map( add )println(list1)
List(2,3,4,5)
如果这个时候,集合的元素有字符串,会出现什么情况?
val list =List(1,2,3,4,"ABC")
def add( obj : Any ): Int ={
obj match {case i:Int => i+1}}
val list1 = list.map( add )println(list1)// 此时程序执行时会发生错误 matcherror
在对符合某个条件,而不是所有情况进行逻辑操作时,使用偏函数是一个不错的选择
将包在大括号内的一组 case 语句封装为函数,我们称之为偏函数,它只对会作用于指定类型的参数或指定范围值的参数实施计算,超出范围的值会忽略(未必会忽略,这取决于你打算怎样处理)
偏函数在 Scala 中是一个特质 PartialFunction
val list =List(1,2,3,"abcd")// 定义一个将 List 集合里面数字加 1 的偏函数// 构建特质的实现类// [Any, Int]是泛型,第一个表示参数类型,第二个表示返回参数
val addOne=newPartialFunction[Any, Int]{
def apply(any: Any)= any.asInstanceOf[Int]+1
def isDefinedAt(any: Any)=if(any.isInstanceOf[Int])trueelsefalse}//val list1 = list.map( addOne ) // // (X) map 函数不支持偏函数
val list1 = list.collect(addOne)// OK collect 函数支持偏函数println(list1)
List(2,3,4)
声明偏函数,需要重新特质中的方法,有的时候会略显麻烦,而 Scala 其实提供了简单的方法
def f2: PartialFunction[Any, Int]={case i: Int => i +1// case 语句可以自动转换为偏函数}
val list1 = list.collect{case i:Int => i +1}// OK collect 函数支持偏函数