Scala模式匹配-创新互联

文章目录
  • Scala 模式匹配
    • 一、模式匹配
      • 1、基本语法
      • 2、语法说明
      • 3、案例示例
    • 二、模式守卫
    • 三、模式匹配类型
      • 1、匹配常量
      • 2、匹配类型
      • 3、匹配数组
      • 4、匹配列表
      • 5、匹配元组
      • 6、匹配对象及样例类
        • (1) 基本语法
        • (2) 优化case样例类
      • 7、偏函数式的模式匹配(了解)

延平网站制作公司哪家好,找创新互联公司!从网页设计、网站建设、微信开发、APP开发、成都响应式网站建设等网站项目制作,到程序开发,运营维护。创新互联公司于2013年创立到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选创新互联公司
Scala 模式匹配 一、模式匹配

Scala 中的模式匹配类似于Java中的switch语法,但是scala 从语法中补充了更多的功能,所以更加强大

1、基本语法

模式匹配语法中,采用match关键字声明,每个分支采用case关键字进行声明,当需要匹配时,会从第一个case分支开始,如果匹配成功,那么执行相对应的逻辑代码,如果匹配不成功,继续执行下一个分支进行判断。如果所有的case都不匹配,那么会执行case…分支,类似于Java中的default语句

2、语法说明

(1) 如果所有case都不匹配,那么会执行case_分支,类似于Java中的default语句,若此时没有case_分支,那么会抛出MatchError
(2) 每个case中,不需要使用break 语句,自动中断case
(3) match case 语句可以匹配任何类型,而不是字面量
(4) =>后面的代码块,直到下一个case 语句之前的代码是作为一个整体执行,可以使用{}括起来,也可以不括

3、案例示例
package Scala04_moshipipei
//模式匹配基本语法
class test01_moshi {}
object test01_moshi{def main(args: Array[String]): Unit = {//1、基本语法定义
    val x:Int = 10
    val y:String = x match {  case 1 =>"one" //如果为1那么返回的是one,中间是=>连接
      case 2 =>"two"
      case 3 =>"there"
      case _ =>"这就是默认情况了,0"
    }//判断x等于什么,如果x为1那么y就是one,如果x为2那么y就是two
    println(y)

    //2、示例;用模式匹配实现简单的二元运算
    val a = 25
    val b = 13
    def hanshu(op:Char) = op match {  case '+' =>a + b
      case '-' =>a - b
      case '*' =>a * b
      case '/' =>a / b
      case '%' =>a % b
      case _ =>"非法运算符"

    }
    println(hanshu('*'))
    println(hanshu('+'))
    println("\\") //传一个字符进去,还要进行转义


  }
}
二、模式守卫

如果想要表达匹配某个范围的数据,就需要在模式匹配中增加条件守卫
注意:num 就是 那个 i,然后调用的时候传入参数进去就可以了

// 模式守卫
    //求一个整数的绝对值
    def fanfga(num:Int) = num match {//num就是下面的那个i
      case i if i >= 0 =>i //定义一个i,如果i大于等于0就返回i
      case i if i< 0 =>-i //如果小于0 那么输出-i,那肯定就是绝对值

    }
    println(fanfga(5))
    println(fanfga(0))
    println(fanfga(-5))

在这里插入图片描述

三、模式匹配类型

Scala 中,模式匹配可以匹配所有的字面量,包括字符串,字符,数字,布尔值等等。
推荐还是把case _加上,因为写的条件可能就那么几个,要是写错了,就会报MatchError

1、匹配常量
//Scala 中,模式匹配可以匹配所有的字面量,包括字符串,字符,数字,布尔值等等。
    //1、匹配常量
    def hanshu(x:Any):String = x match {//返回值不一定非得String,其他的也可以
      case 1 =>"num one" //这就是返回值
      case "hello scala" =>"String hello"
      case true =>"Boolen true" //连布尔类型都可以
      case '+' =>"Char +"
      case _ =>""  //建议还是要设置一个这个,然后条件是有限的,传入参数要是没有就报错了
    }
    println(hanshu(1))
    println(hanshu("hello scala"))
    println(hanshu(true))
    println(hanshu(0.3))

在这里插入图片描述

2、匹配类型

Scala 不仅仅可以匹配常量,还可以匹配数据结构,比如列表,数组.
注意:类型匹配的时候要注意,比如定义了List[String]泛型,规定的定义的是String类型的,但是Int类型的还是匹配上了,因为Scala 的底层有泛型擦除,他只会匹配到是一个list,泛型会自动擦除。而数组比较特殊,它是没有泛型擦除的,所以特别注意这两个地方,容易出现Bug

package Scala04_moshipipei
//模式匹配类型
class test02_pipeileixing {}
object test02_pipeileixing{def main(args: Array[String]): Unit = {//Scala 中,模式匹配可以匹配所有的字面量,包括字符串,字符,数字,布尔值等等。
    //1、匹配常量
    def hanshu(x:Any):String = x match {//返回值不一定非得String,其他的也可以
      case 1 =>"num one" //这就是返回值
      case "hello scala" =>"String hello"
      case true =>"Boolen true" //连布尔类型都可以
      case '+' =>"Char +"
      case _ =>""  //建议还是要设置一个这个,然后条件是有限的,传入参数要是没有就报错了
    }
    println(hanshu(1))
    println(hanshu("hello scala"))
    println(hanshu(true))
    println(hanshu(0.3))

    println("================")
    //2、匹配类型
    def hanshu2(x:Any):String = x match {  case i:Int =>"int" + i //相当于前面规定了这个变量必须的是Int类型的才能匹配上
      case i:String =>"String," + i
      case list: List[String] =>"list:" + list //连List类型都可以定义
      case array:Array[Int] =>"现在是第"+array.mkString(",")+"圈" //因为数组直接输出是引用,所以要用mkString方法输出
      case a =>"Something else:" + a //这是兜底的方法,要拿到值的话就不能用 _ ,必要要设置一个变量
    }
    println(hanshu2(35))
    println(hanshu2("hello"))
    println(hanshu2(List("hi","hello")))
    println(hanshu2(List(2,23)))
    println(hanshu2(Array("hi","hello")))
    println(hanshu2(Array(2,23)))
  }
}

在这里插入图片描述

3、匹配数组

Scala 模式匹配,匹配数组非常强大,可以进行各种模糊的匹配,比如可以匹配必须是三个元素,或者中为1的三个元素的数组。

//3、匹配数组
    for (arr<- List(
      Array(0),
      Array(1,0),
      Array(0,1,0),
      Array(1,1,0),
      Array(2,3,7,15),
      Array("hello",20,30)
    )){ val result = arr match {   case Array(0) =>"0"
       case Array(1,0) =>"1,0"
       case Array(x,y) =>"Array:" + x + y //相当于可以进行模糊查询,匹配两元素数组
       case Array(0,_*) =>"以0开头的数组"
       case Array(x,1,z) =>"中间为1的三元素数组"
       case _ =>"兜底的方法"
     }
      println(result)
    }

在这里插入图片描述

4、匹配列表

列表的匹配有两种方式,第一种和数组的匹配的方式是一样的,
第二种是:case first :: second :: rest =>println(s"first:${first} second:${second} rest,rest是列表,first是第一个元素,second是第二个元素,表示这个列表中至少要有两个元素才能匹配到。列表的这种匹配方式非常常用。

//方式一
    for(list<- List(
      List(0),
      List(1,0),
      List(0,0,0),
      List(1,1,0),
      List(88),
      List("hello")
    )){  val result2 = list match {//这个list就是前面的那个list

        case List(0) =>"0"
        case List(x,y) =>"List(x,y):" + x + "," + y //这个x,y就是两个数的那个列表
        case List(0,_*) =>"List(0,...)" //必须以0开头的列表。后面的个数不限*是通配符
        case List(a) =>"List(a)" //表示list里面只有一个元素
        case _ =>"something else"
      }
      println(result2)

    }
    println("=====================")
    //方式二
    //这种方式在列表匹配里面非常常用
    val list = List(1,2,5,7,24)
    val list1 = List(24)
    list1 match {  case first :: second :: rest =>println(s"first:${first} second:${second} rest ${rest}") //相当于rest是一个列表,第一个元素是first,第二个元素是second
      case _ =>println("something else")
    }
5、匹配元组

元组的匹配跟之前的列表和数组的匹配是非常相似的

for(tuple<- List(
      (0,1),
      (0,0),
      (0,1,0),
      (1,23,56),
      ("hello",true,0.5)
    )){  val result = tuple match {case (a,b) =>println(s"${a},${b}") //这就是一个二元组
        case (0,_) =>println("0,_") //表示第一个元素是0,第二个元素不做要求的一个二元组
        case (a,1,_) =>println("a,1,_"+ a) //表示中间那个元素必须是1,最后一个元素不关心
        case _ =>"something"
      }
      println(result)
    }

除此之外很有很多操作,很灵活

package Scala04_moshipipei
//元组匹配的扩展,元组的匹配是有一点特殊的,是很灵活的
class test03_MatchTuple {}
object test03_MatchTuple{def main(args: Array[String]): Unit = {//1、在变量声明时匹配
    val (x,y) = (10,"hello")
    println(s"${x},${y}")

    val List(first,second,_*) = List(23,15,9,78) //把first赋值给了23,吧second赋值给了15
    println(s"first:${first},second:${second}")

    val fir :: se :: rest = List(23,15,9,78) //想要吧后面两个赋值给一个,那么还是::这种方法
    println(s"first:${fir},second:${se},rest:${rest}")

    //2、for推导式中进行模式匹配
    val list:List[(String,Int)] = List(("a",12),("b",35),("c",27),("a",24))
    for (i<- list){//使用增强for循环进行遍历
      println(i._1 + " " + i._2)
    }
    //2.2 将List的元素直接定义为元组,对变量赋值
    for((word,count)<- list){  println(word+ " " +count) //直接输出就可以了
    }
println("=============")
    //2.3 可以不考虑某个位置的变量,只遍历key或者value
    for((word,_)<- list){  println(word) //这样就得到的全都是key了
    }
println("==================")
    //2.4 指定某个位置的值必须是多少
    for (("a",count)<- list){  println(count) //把所有key是"a"对应的value值都打印出来
    }

  }
}
6、匹配对象及样例类 (1) 基本语法

class User(val name:String,val age:Int)这个可以说是一个非常强大的功能,通过伴生对象里面的值来进行匹配,伴生对象里面要有apply方法,还要有unapply方法,用来对对象属性进行拆解,不然会报错。
步骤简单来说就是,首先定义一个类,然后定义它的伴生对象,然后再伴生对象里面实现apply方法,然后还要是先unapply方法

package Scala04_moshipipei

class test04_Object {}
object test04_Object{def main(args: Array[String]): Unit = {val student = new Student("aex",18)

    //针对对象实例的内容进行匹配

    val result = student match {  case Student("aex",18) =>"aex,18"
      case _ =>"else"
    }
    println(result)

  }
}

//定义类
class Student(val name:String,val age:Int){}
//定义一个伴生对象
object Student {def apply(name: String, age: Int): Student = new Student(name, age)

  //必须实现一个unapply 方法,用来对对象属性进行拆解,这个方法名也是固定的了的,只能为这个
  def unapply(student: Student): Option[(String, Int)] = {if (student == null) {  None
    } else {  Some(student.name, student.age) //这样就拆分出来了
    }
  }


}
(2) 优化case样例类

上面那种方式,虽然实现了,但是太繁琐了违背了scala简洁的定义,所以有了样例类,样例类的定义非常简单,直接在类的前面加上case关键字
例如:case class Student1(val name:String,val age:Int){}
定义了样例类之后,就相当于自动实现了伴生类,apply方apply法和unapply方法,然后可以直接进行对象匹配了

package Scala04_moshipipei
//样例类,对象匹配的简化
class test05_yanglilei {}
object test05_yanglilei{def main(args: Array[String]): Unit = {val student = new Student1("aex",19)

    val result = student match {  case Student1("aex",19) =>"aex,18"
      case _ =>"没有可以进行匹配的"
    }
    println(result)
  }
}

//定义样例类 前面加一个case关键字就可以了
//定义了样例类,就相当于自动实现了伴生对象,apply方法和unapply方法
case class Student1(val name:String,val age:Int){}
7、偏函数式的模式匹配(了解)

偏函数也是函数的一种,通过偏函数我们可以方便的对输入参做更精确的检查。例如该偏函数的输入类型为List[Int],而我们需要的是第一个元素是0的集合,这就是通过模式匹配实现的。
偏函数定义

package Scala04_moshipipei
//偏函数
class test06_PartialFunction {}
object test06_PartialFunction{def main(args: Array[String]): Unit = {val list = List(("a",12),("b",35),("c",27),("a",13)) //二元组

    //1、map转换,实现key不变,value变成原来的2倍
    val newList = list.map(a =>(a._1,a._2*2)) //下滑1第一个元素不变,第二个元素*2
    println(newList)

    //2、模式匹配也可以做这个操作,模式匹配对元组元素赋值,实现功能
    val newList2 = list.map(
      a =>{a match {  case (word,count) =>(word,count*2) //直接这样就赋值了
          case _ =>"没有匹配的"
        }
      }
    )
    println(newList2)
    //3、省略lambda 表达式的写法,进行简化
    val newList3 = list.map{  case (word,count) =>(word,count*2)
  }
    println(newList3)

    //偏函数的应用,求绝对值
    //对输入数据分为不同的情形:正,负,0
    val zheng:PartialFunction[Int,Int] = {//输入的类型是Int,返回的类型也是一个Int
      case x if x >0 =>x
    }
    //这是负数的偏函数
    val fushu:PartialFunction[Int,Int] = {//输入的类型是Int,返回的类型也是一个Int
      case x if x< 0 =>-x
    }
    //这是为0的情况
    val zero:PartialFunction[Int,Int] = {//输入的类型是Int,返回的类型也是一个Int
      case 0 =>0
    }

    def abs(x:Int):Int = (zheng orElse fushu orElse zero ) (x) //前面是作为一个整体

    println(abs(-5))
    println(abs(0))
    println(abs(35))
  }
}

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


本文名称:Scala模式匹配-创新互联
文章分享:http://scyanting.com/article/descie.html