简单匹配Boolean值
val boolSeq = Seq(true, false)
for (bool <- boolSeq) {
bool match {
case true => println("hi true")
case false => println("hi false")
}
}
匹配特定类型的几个值:
for {
x <- Seq(1, 2, 2.7, "one", "two", 'four)
} {
val str = x match {
case 1 => "int 1"
case i: Int => "other int : " + i
case d: Double => "a double: " + d
case "one" => "string one"
case s: String => "other string:" + s
case unexpected => "unexception value :" + unexpected
}
println(str)
}
case _
在结尾作为默认子句,用来匹配任意输入值。
for {
x <- Seq(1, 2, 2.7, "one", "two", 'four)
} {
val str = x match {
case 1 => "int 1"
case _: Int => "other int" + x
case _: Double => "other double" + x
case "one" => "string one"
case _: String => "other string:" + x
case _ => "unexpected value: " + x
}
println(str)
}
case y 的含义其实就是匹配所有输入(由于这里没有类型注解),并将其赋值给新的变量y.这里的y没有被解释为方法参数y.因此,事实上我们将一个默认的,匹配一切的语句写在了第一个,导致系统给出了这条“变量型匹配语句”会匹配一切输入的警告。代码也从未执行到第二条case语句,于是就得到了两条关于不可达代码的警告
def checkX(y: Int) = {
for {
x <- Seq(99, 100, 101)
} {
val str = x match {
case y => "found y!"
case i: Int => "int:" + i
}
println(str)
}
}
checkX(999)
println("------------- check y")
输出结果
------------- check x
found y!
found y!
found y!
case 字句中,以小写字母开头的标识符被认为是用来提取待匹配值的新变量。如果需要引用之前已经定义的变量时,使用反引号将其包围。 于此相对,以大写字母开头的标识符被认为是类型名称:
def checkY(y: Int) = {
for {
x <- Seq(99, 100, 101)
} {
val str = x match {
case `y` => "found y!"
case i: Int => "int:" + i
}
println(str)
}
}
checkY(99)
------------- check y
found y!
int:100
int:101
case字句也持“或”逻辑 :|
/**
* case字句也持“或”逻辑 :|
*/
for {
x <- Seq(1, 2, 2.7, "one", "two", 'four)
} {
val str = x match {
case _: Int | _: Double => "a number: " + x
case "one" => "String one"
case _: String => "other string:" + x
case _ => "unexpected value:" + x
}
println(str)
}
/**
* 序列的模式匹配
*/
object SeqCaseApp extends App {
val nonEmptySeq = Seq(1, 2, 3, 4, 5)
val emptySeq = Seq.empty[Int]
val nonEmptyList = List(1, 2, 3, 4, 5)
val emptyList = Nil
val nonEmptyVector = Vector(1, 2, 3, 4, 5)
val emptyVector = Vector.empty[Int]
val nonEmptyMap = Map("one" -> 1, "two" -> 2, "three" -> 3)
val emptyMap = Map.empty[String, Int]
//定义了一个递归方法,从Seq[T]中构造String,T为某种待定的类型。方法体是用来与输入的Seq[T]相匹配
def seqToString[T](seq: Seq[T]): String = seq match {
case head +: tail => s"$head +: " + seqToString(tail)
case Nil => "Nil"
}
for (seq <- Seq(nonEmptySeq, emptySeq, nonEmptyList, emptyList, nonEmptyVector, emptyVector, nonEmptyMap.toSeq, emptyMap.toSeq)) {
println(seqToString(seq))
}
}
扫描元组的字面量,很容易对元祖进行匹配:
package base.caseT
object TupleCaseApp extends App {
val langs = Seq(
("Scala", "Java", "Clojure"),
("Clojure", "Rich", "python")
)
for (tuple <- langs) {
tuple match {
case ("Scala", _, _) => println("found scala")
case (lang, first, last) => println(s"found other language : $lang ($first, $last)")
}
}
// 打印1,2
(1,2) match {
case (a,b) => println(a+","+b)
}
// 打印2
(1,2) match {
case (1, b) => println(b)
}
// 打印found
(1,2) match {
case (_, 2) => println("found")
}
// 得到List(1,2)
List(1,2,3,4) match {
case a :: b :: other => List(a, b)
case _ => List()
}
/**
* guard 语句
*/
for (i <- Seq(1, 2, 3, 4)) {
i match {
case _ if i % 2 == 0 => println(s"even: $i")
case _ => println(s"odd: $i")
}
}
}
case类的匹配,可以对case类对象的内容进行考察:
package base.caseT
/**
* 匹配嵌套类型的内容
*/
object ClassCaseApp extends App {
case class Address(street: String, city: String, country: String)
case class Person(name: String, age: Int, address: Address)
val alice = Person("Alice", 25, Address("101", "杭州", "拱墅区"))
val bob = Person("Bob", 29, Address("102", "北京", "望京"))
val marry = Person("Marry", 25, Address("103", "南京", "栖霞区"))
for(person <- Seq(alice, bob, marry)) {
person match {
case Person("Alice", 25, Address(_, "杭州", _)) => println("Hi Alice")
case Person("Bob", 29, Address(_, "北京", _)) => println("Hi Bob")
case Person(name, age, _) => println(s"who are you, $age year-old person named $name?")
}
}
}
当一个类被声名为case class的时候,scala会帮助我们做下面几件事情:
package base
abstract class A
package base
case class B(name:String, age:Int) extends base.A
case object CaseObject extends base.A{
}
执行命令编译脚本:
scalac A.scala
scalac B.scala
scalac CaseObject.scala
case class B反编译如下:
pjx@pjxdeMacBook-Pro:~/program/scala-2.12.5/bin/base$ javap -private B.class
Compiled from "B.scala"
public class base.B extends base.A implements scala.Product,scala.Serializable {
private final java.lang.String name;
private final int age;
public static scala.Option> unapply(base.B);
//自动生成半生对象
public static base.B apply(java.lang.String, int);
public static scala.Function1, base.B> tupled();
public static scala.Function1> curried();
public java.lang.String name();
public int age();
public base.B copy(java.lang.String, int);
public java.lang.String copy$default$1();
public int copy$default$2();
public java.lang.String productPrefix();
public int productArity();
public java.lang.Object productElement(int);
public scala.collection.Iterator productIterator();
public boolean canEqual(java.lang.Object);
public int hashCode();
public java.lang.String toString();
public boolean equals(java.lang.Object);
public base.B(java.lang.String, int);
}
CaseObject反编译如下:
pjx@pjxdeMacBook-Pro:~/program/scala-2.12.5/bin/base$ javap -private ../CaseObject.class
Compiled from "CaseObject.scala"
public final class CaseObject {
public static java.lang.String toString();
public static int hashCode();
public static boolean canEqual(java.lang.Object);
public static scala.collection.Iterator productIterator();
public static java.lang.Object productElement(int);
public static int productArity();
public static java.lang.String productPrefix();
}
pjx@pjxdeMacBook-Pro:~/program/scala-2.12.5/bin/base$ javap -private ../CaseObject$.class
Compiled from "CaseObject.scala"
public final class CaseObject$ extends base.A implements scala.Product,scala.Serializable {
public static CaseObject$ MODULE$;
public static {};
public java.lang.String productPrefix();
public int productArity();
public java.lang.Object productElement(int);
public scala.collection.Iterator productIterator();
public boolean canEqual(java.lang.Object);
public int hashCode();
public java.lang.String toString();
private java.lang.Object readResolve();
private CaseObject$();
}
case object
与case class
不同的是,没有apply
和unapply
方法,这是因为None
不需要创建对象及进行内容提取。