多语言展示
当前在线:976今日阅读:91今日分享:37

Scala模式匹配、类型系统与Spark源码阅读

Scala模式匹配、类型系统彻底精通与Spark源码阅读
方法/步骤
1

一、守卫   var ch = ‘+’   ch match {      case '+' => sign = 1      case '-' => sign = -1      case _ if Character.isDigit(ch) => digit= Character.digit(ch, 10)      case _ => sign = 0   }

2

二、模式中的变量如果在case关键字后跟着一个变量名,那么匹配的表达式会被赋值给那个变量。case _是这个特性的一个特殊情况,变量名是_。    'Hello, world' foreach { c =>println (        c match {          case ' ' => 'space'          case ch => 'Char: ' + c      }    )}

3

三、类型模式相比使用isInstanceOf来判断类型,使用模式匹配更好    obj match {       case x: Int => x       case s: String => Integer.parseInt(s)       case _: BigInt => Int.MaxValue       case _ => 0    }捕获异常:    val file = new File(fileName)    try {         Source.fromFile(file).getLines()    }catch{         case e1: FileNotFoundException=> println('FileNotFoundException')         case e2: RuntimeException =>println('RuntimeException')        case e3: Exception =>println('Exception')     }因为匹配是发生在运行期的,而且JVM中泛型的类型信息会被擦掉,因此不能使用类型来匹配特定的Map类型

4

四、匹配数组、列表和元组1)数组      valarr = Array(0,3,4,5,6,7)      arr match {        case Array(0) => '0'        case Array(x, y) => x + ' '+ y        case Array(0, x @_*) => println(x)        case _ => 'something else'      }2) 列表      val arr = List(0,4,5,6,7,)      arrmatch {        case List(0) => '0'        case List(x, y) => x + ' ' + y        case List(0, x @_*) => println(x)        case _ => 'something else'     }     或者     arr match {        case 0 :: Nil => '0'        case x :: y :: Nil => x + '' + y        case 0 :: tail => '0...'        case _ => 'somethingelse'     }

5

五、提取器模式匹配来对数组、列表和元组进行了匹配,在这个过程的背后的是提取器(extractor)机制。使用unapply来提取固定数量的对象,使用unapplySeq来提取一个序列。在前面的代码 case Array(0, x) => ...中, Array(0, x)部分实际上是使用了伴生对象中的提取器,实际调用形式是: Array.unapplySeq(arr)。根据Doc,提取器方法接受一个Array参数,返回一个Option。1)正则表达式是另一个适用提取器的场景。正则有分组时,可以用提取器来匹配分组       val pattern = '([0-9]+)([a-z]+)'.r       '99 bottles' match {casepattern(num, item) => (num, item)}2)自定义提取器;下面的例子显示电子邮件地址的提取器对象:object Test {      def main(args: Array[String]) {         println ('Apply method : ' +apply('Zara', 'gmail.com'));         println ('Unapply method : ' +unapply('Zara@gmail.com'));         println ('Unapply method : ' +unapply('Zara Ali'));      }   // The injection method (optional)   def apply(user: String, domain: String) = {      user +'@'+ domain   }   // The extraction method (mandatory)   def unapply(str: String): Option[(String,String)] = {      val parts = str split '@'      if (parts.length == 2){         Some(parts(0), parts(1))      }else{        None      }   }}

6

六、变量声明中的模式   val (x, y) = (1, 2)   val (q, r) = BigInt(10) /% 3  // 返回商和余数的对偶   val Array(first, second, _*) =arr  // 将第一和第二个分别给first和second

7

七、for表达式中的模式   importscala.collection.JavaConversions.propertiesAsScalaMap   for ((k, v) <-System.getProperties())  // 这里使用了模式      println(k + ' -> ' + v)   for ((k, '') <-System.getProperties())  // 失败的匹配会被忽略,所以只打印出值为空的键      println(k)

8

八、样例类   abstract class Amount   // 继承了普通类的两个样例类   case class Dollar(value: Double) extends Amount   case class Currency(value: Double, unit:String) extends Amount   // 样例对象   case object Nothing extends Amount   amt match {      case Dollar(v) => '$' + v      case Currency(_, u) => 'Oh noes, Igot ' + u      case Nothing => ''  //样例对象没有()   }在声明样例类时,下面的过程自动发生了:构造器的每个参数都成为val,除非显式被声明为var,但是并不推荐这么做;在伴生对象中提供了apply方法,所以可以不使用new关键字就可构建对象;提供unapply方法使模式匹配可以工作;生成toString、equals、hashCode和copy方法,除非显示给出这些方法的定义。除了上述之外,样例类和其他类型完全一样,方法字段等。

9

九、匹配嵌套结构  abstarct class Item  case class Article(description: String,price: Double) extends Item  case class Bundle(description: String, price:Double, items: Item*) extends Item  Bundle('Father's day special',20.0,     Article('Scala for the Impatient',39.95),     Bundle('Anchor DistillerySampler', 10.0,     Article('Old Potrero Straight RyeWhisky', 79.95),     Article('Junipero Gin', 32.95)     )  )  模式可以匹配到特定的嵌套:  case Bundle(_, _, Article(descr, _), _*) =>descr

10

十、密封类当使用样例类来做模式匹配时,如果要让编译器确保已经列出所有可能的选择,可以将样例类的通用超类声明为sealed。密封类的所有子类都必须在与该密封类相同的文件中定义。如果某个类是密封的,那么在编译期所有的子类是可知的,因而可以检查模式语句的完整性。让所有同一组的样例类都扩展某个密封的类或特质是个好的做法。   sealed abstract class TrafficLightColor   case object Red extends TrafficLightColor   case object Yellow extends TrafficLightColor   case object Green extends TrafficLightColor   color match {      case Red => 'stop'      case Yellow => 'hurry up'      case Green => 'go'  }

11

十一、Option类型Option类型用来表示可能存在也可能不存在的值。样例子类Some包装了某个值,而样例对象None表示没有值。Option支持泛型。   val map = Map(3 -> “a”, 4 -> “b”)   map.get(3) match {      case Some(x) => x      case Nome   }

12

十二、偏函数被包在花括号内的一组case语句是一个偏函数。偏函数是一个并非对所有输入值都有定义的函数,是PartialFunction[A, B]类的一个实例,其中A是参数类型,B是返回类型。该类有两个方法:apply方法从匹配的模式计算函数值;isDefinedAt方法在输入至少匹配其中一个模式时返回true。   val f:PartialFunction[Char, Int] = { case '+' => 1; case '-' => -1 }   f('-')  //返回-1   f.isDefinedAt('0')  //false   f('0')  //抛出MatchError

推荐信息