1869 4

第4课:Scala模式匹配、类型系统彻底精通与Spark源码阅读 [推广有奖]

  • 1关注
  • 8粉丝

硕士生

34%

还不是VIP/贵宾

-

威望
0
论坛币
305 个
通用积分
0
学术水平
5 点
热心指数
14 点
信用等级
2 点
经验
23002 点
帖子
73
精华
0
在线时间
135 小时
注册时间
2016-2-27
最后登录
2016-9-11

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

一、守卫

   var ch = ‘+’
   ch match {

      case '+' => sign = 1

      case '-' => sign = -1

      case _ if Character.isDigit(ch) => digit= Character.digit(ch, 10)

      case _ => sign = 0

   }



二、模式中的变量

如果在case关键字后跟着一个变量名,那么匹配的表达式会被赋值给那个变量。case _是这个特性的一个特殊情况,变量名是_。

    "Hello, world" foreach { c =>println (

        c match {

          case ' ' => "space"

          case ch => "Char: " + c

      }

    )}



三、类型模式

相比使用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类型


四、匹配数组、列表和元组

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"

     }


五、提取器

模式匹配来对数组、列表和元组进行了匹配,在这个过程的背后的是提取器(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

      }

   }

}



六、变量声明中的模式

   val (x, y) = (1, 2)

   val (q, r) = BigInt(10) /% 3  // 返回商和余数的对偶

   val Array(first, second, _*) =arr  // 将第一和第二个分别给first和second



七、for表达式中的模式

   importscala.collection.JavaConversions.propertiesAsScalaMap

   for ((k, v) <-System.getProperties())  // 这里使用了模式

      println(k + " -> " + v)

   for ((k, "") <-System.getProperties())  // 失败的匹配会被忽略,所以只打印出值为空的键

      println(k)



八、样例类

   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方法,除非显示给出这些方法的定义。

除了上述之外,样例类和其他类型完全一样,方法字段等。



九、匹配嵌套结构

  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



十、密封类

当使用样例类来做模式匹配时,如果要让编译器确保已经列出所有可能的选择,可以将样例类的通用超类声明为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"

  }



十一、Option类型

Option类型用来表示可能存在也可能不存在的值。样例子类Some包装了某个值,而样例对象None表示没有值。Option支持泛型。

   val map = Map(3 -> “a”, 4 -> “b”)

   map.get(3) match {

      case Some(x) => x

      case Nome

   }



十二、偏函数

被包在花括号内的一组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




注:本学习笔记来自DT大数据梦工厂

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:Spark SCALA SPAR Park SPA Spark Scala DT_Spark 大数据

已有 1 人评分经验 论坛币 收起 理由
daazx + 40 + 10 精彩帖子

总评分: 经验 + 40  论坛币 + 10   查看全部评分

沙发
cxljkb110 发表于 2016-3-29 20:30:37 |只看作者 |坛友微信交流群
好文,顶顶顶

使用道具

cxljkb110 发表于 2016-3-29 20:30
好文,顶顶顶

使用道具

板凳
c985799258 发表于 2016-5-2 11:37:34 |只看作者 |坛友微信交流群
thanks

使用道具

c985799258 发表于 2016-5-2 11:37
thanks
贫道不胜荣幸!

使用道具

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2024-5-1 15:25