一. 更好的switch:match
- match匹配任何类型
scala> var ch = '*' ch: Char = * scala> var sign="" sign: String = "" scala> ch match{ // match表达式 | case '+' => sign="1" | case '-' => sign="-1" | case _ => sign="not in +/-" | } scala> print(sign) not in +/-
【注】:
(1)与java不同,match中的每个case语句,不需要显示的声明break,不用担心“跳入下一个分支”
(2)如果未声明case _ 来匹配任一选项,则会抛出MatchError异常
(3) 与if类似,match是表达式,而非语句
-
带守卫的match
守卫是一个boolean类型的条件,用来给case _加限定条件scala> ch match { | case '+' => sign="0" | case _ if Character.isDigit(ch) => sign="is digit" // 守卫 | case _ => sign="orthers" | } scala> print(sign) is digit
-
case的常量匹配
case可用常量匹配,scala识别常量的方法是:以大写字母开头的名字认为是常量。所以,如果匹配小写字母开头的常量,需要将常量用反引号扩起来scala> val ADD = "+" ADD: String = + scala> var ch = "+" ch: String = + scala> ch match { | case ADD => print("111") // 大写开头的ADD,scala自动识别为常量匹配 | case "-" => print("222") | } 111 scala> val add="+" scala> ch match { | case `add` => print("111") // 小写字母开头的常量反引号引起来:`add` | case "-" => print("222") | } 111
-
变量数值类型的匹配
(1)scala用match匹配变量的参数类型,而不去时用isInstanceOf操作符
(2)如果match返回的结果依赖于需要匹配的变量值,则case语句后面加上别名
(3)类型匹配不能去匹配集合泛型,因为泛型是编译时期约束,而match是运行时代码var obj:Any = "11" val result = obj match{ case x: Int => 2 * x case s: String => Integer.parseInt(s)+"aaa" case _ => 0 } println(obj) //11 println(result) //11aaa var obj2:Any="11" val result2 = obj2 match { case _ : Int => 111 // result2的表达式用不上obj2,不用起别名 case _ => 0 } println(result2)
-
数组,List, 元组的模式匹配
(1)数组:数组的匹配项可以匹配任意长度的Array
(2)List:list时固定长度的列表,list分为head和tail2部门,head时list的第一个元素,tail是list中除了head外的其余元素组成的list。用::连接list时,尾节点要声明成Nil
(3)元组:元组的匹配项,要与原元组用相同的元素个数,元素类型//1. Array匹配 var arr = Array(1,2,3) val s: String = arr match { case Array(0) => "0" case Array(x,y) => "2 param array" case Array(1, _*) => "1 ..." case _ => "anything else" } print(s) //2. List匹配 var digitList = List(1,2,4) var list2 = 9 :: List(4,2) :: 2 :: Nil //list val value: Any = list2 match { case 9 :: Nil => 9 case x :: y :: Nil => x + "" + y case _ => "something else" } print(value) //something else //3. 元组匹配 var tuple1 = (1,"abc",'d') tuple1 match { case (0,"asd", _) => "haha" case (x,y,'d') => "d" case _ => "anything" }
三. 其他模式
-
集合声明中的模式
(1)元组声明中的变量匹配val (x,y) = (1,2) print(x) //1
(2)数组声明中的变量匹配
scala val arr = Array(1,2,3) var Array(first,scend,3) = arr print(first) //1
- for推导式的模式匹配
import scala.collection.JavaConversions.propertiesAsScalaMap //将java的properties转换成scala的映射 for((k,v) <- System.getProperties){ print(k+"==>"+v) } for((k,"") <- System.getProperties){ println(k) } // 带守卫的for for((k,v) <- System.getProperties if v==""){ println(k) }
四. 样例类
-
case类与普通类的区别
(1)构造器的每一个参数都默认为val的,除非它被显式地声明成var
(2)case类的伴生对象自动加上apply方法,使得不用new关键字就能构造处对象
(3)自动生成unapply()方法供提取器模式匹配
(4)自动产生toString,equals,hashCode,copy方法。其他特性和普通类相同,如继承等abstract class Amount case class Dollar(value:Double) extends Amount //样例类 case class Currency(value:Double,unit:String) extends Amount case object Nothing extends Amount //样例对象 //样例类模式匹配 val amt:Any = Currency(11.2,"asd") val s: String = amt match { case Dollar(v) => "$" + v case Currency(_, v) => "i got " + v case Nothing => "" } s //i got asd class A(value:String){} var aa = new A("111") //普通类不会自动加上apply()
-
copy方法和带名参数
copy()方法创建了一个与对象值相同的新对象,可以制定参数值类构建新对象val amt2 = Currency(29.95,"EUR") val price = amt2.copy() //price: Currency = Currency(29.95,EUR) val price2 = amt2.copy(value=11.2) //price2: Currency = Currency(11.2,EUR) val price3 = amt2.copy(unit="CHF") //price3: Currency = Currency(29.95,CHF)
五. Option类型
- Option类是一个样例类,常用于表示函数的返回值类型:Option[T]。表示那种可能存在,也可能不存在的值。
- 存在的值用子类Some包装。eg:Some("Fred"),表示返回fred字符串
- 不存在的值用None表示
object Test extends App{ private val map: Map[String, Int] = Map(("fred",1),("lucy",2)) map.get("fred") match { // map的get方法返回Option类型,模式匹配用Some或none匹配 case Some(1) => println(1) case None => println("no value") } //getOrElse方法利用上面的模式匹配 map.getOrElse("zhangsan",{println("no value")}) //no value }
六. 偏函数
- 偏函数:没有定义所有情况的case语句块
- 偏函数常用于参数传入
object TestLazyView extends App{ val res = "-3+4".collect({case '-' => 1;case '+' => -1}) //Vector(1, -1) println(res) }