12.1 match
12.1.1 Basic Introduction
Schema matching in Scala is similar to switch syntax in Java, but more powerful
In pattern matching grammar, match keyword declaration is used, and case keyword declaration is used for each branch. When matching is needed, the first case branch will start. If matching is successful, the corresponding logic code will be executed. If matching is unsuccessful, the next branch will be executed for judgment. If all cases do not match, case_branches are executed, similar to default statements in Java
12.1.2 Quick Start Case of Scala's match
object boke_demo01 { def main(args: Array[String]): Unit = { val oper = '+' val n1 = 20 val n2 = 10 var res = 0 //Explain //1. match (like java switch) and case are keywords //2. If the match is successful, the code block following => is executed. //3. The order of matching is from top to bottom. When matched to one, the corresponding code is executed. //4. => The following code block does not write break and will automatically exit match. //5. If none of them matches, execute the block after case_ oper match { case '+' => { res = n1 + n2 println("ok~~") println("hello~~") } case '-' => res = n1 - n2 case '*' => res = n1 * n2 case '/' => res = n1 / n2 case 1 => println("Match to 1") case 1.1 => println("Match 1.1") case _ => println("oper error") } println("res=" + res) } }
12.1.3 match Details and Notes
If all cases do not match, case_branches are executed, similar to default statements in Java
2) If all cases do not match and case_branches are not written, MatchError will be thrown
3) Automatically interrupt case without break statement in each case
4) You can use other types in match es, not just characters
5) => equivalent to java switch:
6) => The following block of code to the next case is executed as a whole, which can be expanded by {} or not.
12.2 guard
12.2.1 Basic Introduction
If you want to express data that matches a certain range, you need to add conditional guards in pattern matching
12.2.2 Application Cases
object boke_demo01 { def main(args: Array[String]): Unit = { for (ch <- "+-3!") { //Yes, "+-3!" traversal var sign = 0 var digit = 0 ch match { case '+' => sign = 1 case '-' => sign = -1 // Explain.. // If conditional guard is if after case, then does not mean default matching // Indicates that the incoming ch is ignored case _ if ch.toString.equals("3") => digit = 3 case _ => sign = 2 } //Analysis // + 1 0 // - -1 0 // 3 0 3 // ! 2 0 println(ch + " " + sign + " " + digit) } } }
Variables in the 12.3 model
12.3.1 Basic Introduction
If the case keyword is followed by the variable name, the value of the expression before match is assigned to that variable
12.3.2 Application Cases
object boke_demo01 { def main(args: Array[String]): Unit = { val ch = 'U' ch match { case '+' => println("ok~") // The following case mychar means mychar = ch case mychar => println("ok~" + mychar) case _ => println("ok~~") } val ch1 = '+' //match is an expression, so you can have a return value //The return value is the value of the last sentence of the matched block of code val res = ch1 match { case '+' => ch1 + " hello " case _ => println("ok~~") } println("res=" + res) } }
12.4 Type Matching
12.4.1 Basic Introduction
You can match any type of object without using isInstanceOf and asInstanceOf
12.4.2 Application Cases
object boke_demo01 { def main(args: Array[String]): Unit = { val a = 8 //Explain that the type of obj instance is returned based on the value of a val obj = if (a == 1) 1 else if (a == 2) "2" else if (a == 3) BigInt(3) else if (a == 4) Map("aa" -> 1) else if (a == 5) Map(1 -> "aa") else if (a == 6) Array(1, 2, 3) else if (a == 7) Array("aa", 1) else if (a == 8) Array("aa") //Explain //1. Matching according to the type of obj // Return value val result = obj match { case a: Int => a case b: Map[String, Int] => "Object is a string-Digital Map aggregate" case c: Map[Int, String] => "Object is a number-String Map aggregate" case d: Array[String] => d //"Object is an array of strings" case e: Array[Int] => "Object is an array of numbers" case f: BigInt => Int.MaxValue case y: Float => println("xx") case _ => "Nothing" } println(result) } }
12.4.3 Matching Notes
Map [String, Int] and Map[Int, String] are two different types, other analogies
2) When type matching is performed, the compiler will detect in advance whether a possible match is possible, and if not, it will report an error.
object boke_demo01 { def main(args: Array[String]): Unit = { val obj = 10 val result = obj match { case a: Int => a //Case b: Map [String, Int]=> Map Collection // Errors will be reported after uncommentation case _ => "Nothing" } } }
4) If case_appears in the middle of match, it means hidden variable names, i.e., no use, not default matches.
12.5 Matching Array
12.5.1 Basic Introduction
Array (0) matches an array with only one element and zero
2) Array(x,y) matches the array with two elements and assigns them to X and y. Of course, you can analogize Array(x,y,z) matching arrays in turn with three elements, and so on.
3) Array(0, *) matching array starts with 0
12.5.2 Application Cases
import scala.collection.mutable.ArrayBuffer object boke_demo01 { def main(args: Array[String]): Unit = { // val arrs = Array(Array(0), Array(1, 0), Array(0, 1, 0), // Array(1, 1, 0), Array(1, 1, 0, 1)) // // for (arr <- arrs ) { // val result = arr match { // case Array(0) => "0" // case Array(x, y) => x + "=" + y // Case Array (0, *) => "Start with 0 and arrays" // Case => "No set" // } // // result = 0 // // result = 1 = 0 // // result = starts with 0 and arrays // // result = no set // // result = no set // println("result = " + result) // } //Give you a collection of arrays. If the array is Array(10,20), use the default match and return to Array(20,10). val arrs2 = Array(Array(0), Array(1, 0), Array(0, 1, 0), Array(1, 1, 0), Array(1, 1, 0, 1)) for (arr <- arrs2) { val result = arr match { //case Array(0) => "0" case Array(x, y) => ArrayBuffer(y, x) //Array(y,x).toBuffer //? ArrayB(y,x) //Case Array (0, *) => "Start with 0 and arrays" case _ => "Not deal with~~" } println("res=" + result) //ArrayBuffer(0,1) } } }
12.6 Matching List
Case demonstration
object boke_demo01 { def main(args: Array[String]): Unit = { for (list <- Array(List(0), List(1, 0), List(0, 0, 0), List(1, 0, 0))) { val result = list match { case 0 :: Nil => "0" // case x :: y :: Nil => x + " " + y // case 0 :: tail => "0 ..." // case x :: Nil => x case _ => "something else" } //1. 0 //2. 1 0 //3. 0 ... //4. something else println(result) } } }
12.7 Matching tuples
Case demonstration
object boke_demo01 { def main(args: Array[String]): Unit = { //If you want to match (10, 30) a dual tuple of any two elements, how should you write for (pair <- Array((0, 1), (1, 0), (10, 30), (1, 1), (1, 0, 2))) { val result = pair match { // case (0, _) => "0 ..." // case (y, 0) => y // case (x, y) => (y, x) //"Match to (x, y)"+x+y"+y case _ => "other" //. } //1. 0 ... //2. 1 //3. (30,10) //4. (1,1) //5. other println(result) } } }
12.8 Object Matching
12.8.1 Basic Introduction
Object matching, what is matching? The rules are as follows:
1) The unapply method of the object in case (object extractor) returns to the Some set for successful matching.
2) Returning to None sets is a matching failure
12.8.2 Quick Start
object boke_demo01 { def main(args: Array[String]): Unit = { // Pattern matching uses: val number: Double = Square(6.0) // 36.0 // number match { //Explain the operating mechanism of case Square(n) //1. When matched to case Square(n) //2. Call unapply (z: Double) of Square, and the value of Z is number. //3. If the object extractor unapply(z: Double) returns Some(6), then the match is successful, and at the same time // Assign 6 to n of Square(n) //4. If the object extractor unapply(z: Double) returns None, the matching is unsuccessful. case Square(n) => println("Matching success n=" + n) case _ => println("nothing matched") } } } //Explain object Square { //Explain //1. unapply method is object extractor //2. Receive z:Double type //3. The return type is Option[Double] //4. The value returned is Some(math.sqrt(z)) which returns the open square value of Z and puts it into Some(x) def unapply(z: Double): Option[Double] = { println("unapply Be called z yes=" + z) Some(math.sqrt(z)) //None } def apply(z: Double): Double = z * z }
12.8.3 Application Case 2
Case demonstration
object boke_demo01 { def main(args: Array[String]): Unit = { val namesString = "Alice,Tom,Jack" //Character string //Explain namesString match { // When executing case Names(first, second, third) // 1. Call unapplySeq (str) to pass "Alice,Tom,Jack" to str // 2. If you return Some("Alice","Tom","Jack"), give them to (first, second, third) respectively. // Note that the number of returned values here needs to be the same as (first, second, third) // 3. If None is returned, the match fails case Names(first, second, third) => { println("the string contains three people's names") // Print string println(s"$first $second $third") } case _ => println("nothing matched") } } } //object object Names { //When the constructor is multiple parameters, the object extractor is triggered def unapplySeq(str: String): Option[Seq[String]] = { if (str.contains(",")) Some(str.split(",")) else None } }
Summary of Case Demonstration
def unapplySeq() method is called by default when the parameters of the object extractor method behind case are more than one.
2) If unapplySeq returns Some, get the value, judge whether the number of elements in the sequence is three, if three, then take out the three elements separately and assign them to first, second and third?
3) Other rules remain unchanged
Patterns in 12.9 Variable Declarations
12.9.1 Basic Introduction
Each case in a match can be taken out separately, meaning the same
12.9.2 Application Cases
object boke_demo01 { def main(args: Array[String]): Unit = { val (x, y, z) = (1, 2, "hello") println("x=" + x) val (q, r) = BigInt(10) /% 3 //Note q = BigInt (10) / 3R = BigInt (10)% 3 val arr = Array(1, 7, 2, 9) val Array(first, second, _*) = arr // The first two elements of arr are proposed println(first, second) } }
12.10 for expressions
12.10.1 Basic Introduction
for loops can also perform pattern matching
12.10.2 Application Cases
object boke_demo01 { def main(args: Array[String]): Unit = { val map = Map("A" -> 1, "B" -> 0, "C" -> 3) for ((k, v) <- map) { println(k + " -> " + v) // Three key-value ("A"-> 1), ("B"-> 0), ("C"-> 3) } //Note: Only key-value of value =0 is traversed, and the others are filtered out. println("--------------(k, 0) <- map-------------------") for ((k, 0) <- map) { println(k + " --> " + 0) } //Note that this is another way to write the above code, but the following usage is flexible and powerful println("--------------(k, v) <- map if v == 0-------------------") for ((k, v) <- map if v >= 1) { println(k + " ---> " + v) } } }
12.11 Sample (Template) Category
12.11.1 Quick Start of Sample Class
object CaseClassDemo01 { def main(args: Array[String]): Unit = { println("hello~~") } } abstract class Amount case class Dollar(value: Double) extends Amount //case class case class Currency(value: Double, unit: String) extends Amount //case class case object NoAmount extends Amount //case class
12.11.2 Basic Introduction
1) Sample classes are still classes
2) Sample classes are declared with case keywords
3) Sample classes are optimized for pattern matching
4) Every parameter in the constructor becomes val unless it is explicitly declared var (not recommended).
5) Provide an apply method in the associated object of the sample class, which can construct the corresponding object without using the new keyword.
6) Provide unapply methods to make pattern matching work
7) toString, equals, hashCode, and copy methods will be generated automatically (a bit like template classes, directly for programmers to use)
8) Except for the above, the sample class is exactly the same as other classes. Fields and methods can be added to extend them
12.11.3 Application Case 1
Case demonstration
object boke_demo01 { def main(args: Array[String]): Unit = { //The role of this case is to experience the simplicity of object matching using sample classes for (amt <- Array(Dollar(1000.0), Currency(1000.0, "RMB"), NoAmount)) { val result = amt match { //Explain case Dollar(v) => "$" + v // $1000.0 //Explain case Currency(v, u) => v + " " + u // 1000.0 RMB case NoAmount => "NoAmount" // NoAmount } println(amt + ": " + result) } } } abstract class Amount case class Dollar(value: Double) extends Amount //case class case class Currency(value: Double, unit: String) extends Amount //case class case object NoAmount extends Amount //case class
12.11.4 Application Case 2
Explanation
copy method and named parameter of sample class
copy creates a new object with the same value as an existing object, and can modify certain properties with named parameters
Case demonstration
object boke_demo01 { def main(args: Array[String]): Unit = { val amt = new Currency(3000.0, "RMB") val amt2 = amt.copy() // Cloning, creating objects with the same attributes as amt println("amt2.value" + amt2.value + " amt2.unit= " + amt2.unit) println(amt2) val amt3 = amt.copy(value = 8000.0) println(amt3) val amt4 = amt.copy(unit = "dollar") println(amt4) } } abstract class Amount case class Dollar(value: Double) extends Amount //case class case class Currency(value: Double, unit: String) extends Amount //case class case object NoAmount extends Amount //case class
12.12 case Statement's Intermediate (Affix) Expressions
12.12.1 Basic Introduction
What is an intermediate expression? 1 + 2, that's a middle expression. If the unapply method produces a tuple, the middle representation can be used in case statements. For example, you can match a List sequence
12.12.2 Application Cases
Case demonstration
object boke_demo01 { def main(args: Array[String]): Unit = { List(1, 3, 5, 9) match { //Modify and test //1. Between two elements: called the middle expression, at least the first, second two matches. //2.first matches the first second matches the second, rest matches the rest (5,9) case first :: second :: rest => println(first + " " + second + " " + rest.length + " " + rest) // case _ => println("No match...") } } }
12.13 Seals
12.13.1 Basic Introduction
1) If you want all subclasses of a case class to be defined in the same source file that declares that class, you can declare the generic superclass of the sample class sealed, which is called a sealed class.
2) Sealing means that subclasses cannot be defined in other files