1. Pattern matching
Scala has a very powerful pattern matching mechanism and is widely used, such as:
- Judge fixed value
- Type query
- Get data quickly
1.1 simple pattern matching
A pattern matching contains a series of alternatives, each of which starts with the keyword case. Each alternative contains a pattern and one or more expressions. The arrow symbol = > separates the pattern from the expression.
variable match { case "Constant 1" => Expression 1 case "Constant 2" => Expression 2 case "Constant 3" => Expression 3 case _ => Expression 4 // Default matches }
Execution process
- First execute the first case to see whether the variable value is consistent with the constant value corresponding to the case
- If consistent, execute the expression corresponding to the case
- If not, execute the next case later to see if the variable value is consistent with the constant value corresponding to the case
- And so on, if all cases do not match, the case is executed_ Corresponding expression
Example
import scala.io.StdIn //Case: simple matching of pattern matching object ClassDemo01 { def main(args: Array[String]): Unit = { //1. Prompt the user to enter a string and receive it println("Please enter a string: ") var str = StdIn.readLine() //2. Judge whether the string is the specified content and receive the result val result = str match { case "hadoop" => "Big data distributed storage and computing framework" case "zookeeper" => "Big data distributed coordination service framework" case "spark" => "Big data distributed memory computing framework" case _ => "Unmatched" } //3. Print results println(result) println("-" * 15) //Split line //Abbreviated form str match { case "hadoop" => println("Big data distributed storage and computing framework") case "zookeeper" => println("Big data distributed coordination service framework") case "spark" => println("Big data distributed memory computing framework") case _ => println("Unmatched") } } }
1.2 matching type
In addition to matching data, match expressions can also perform type matching. If we want to execute different logic according to different data types, we can also use match expressions.
Object name match { case Variable name 1: Type 1 => Expression 1 case Variable name 2: Type 2 => Expression 2 case Variable name 3: Type 3 => Expression 3 ... case _ => Expression 4 }
- Note: if the matched variable does not need to be used in the case expression, the underscore can be used instead
Example
//Case: matching type of pattern matching object ClassDemo02 { def main(args: Array[String]): Unit = { //1. Define a variable as Any type, and then assign it "hadoop", 1 and 1.0 respectively val a: Any = 1.0 //2. Define pattern matching, and then print the name of the type respectively val result = a match { case x: String => s"${x} yes String Type of data" case x: Double => s"${x} yes Double Type of data" case x: Int => s"${x} yes Int Type of data" case _ => "Unmatched" } //3. Print results println(result) //4. The optimized version can be used if the variable is not used during case verification_ replace. val result2 = a match { case _: String => "String" case _: Double => "Double" case _: Int => "Int" case _ => "Unmatched" } //Print results println(result2) } }
1.3 guard
The so-called guard means adding if conditional judgment to the case statement, which can make our code more concise and elegant
variable match { case Variable name if Condition 1 => Expression 1 case Variable name if Condition 2 => Expression 2 case Variable name if Condition 3 => Expression 3 ... case _ => Expression 4 }
Example
import scala.io.StdIn //Case: guard of pattern matching object ClassDemo03 { def main(args: Array[String]): Unit = { //1. Read a number a from the console (using StdIn.readInt) println("Please enter an integer: ") var num = StdIn.readInt() //2. Pattern matching num match { //2.1 if a > = 0 and a < = 3, print [0-3] case a if a >= 0 && a <= 3 => println("[0-3]") //2.2 if a > = 4 and a < = 8, print [4,8] case a if a >= 4 && a <= 8 => println("[4-8]") //2.3 otherwise, the print does not match case _ => println("Unmatched") } } }
1.4 matching sample classes
In Scala, pattern matching can be used to match the sample class, so that the member data in the sample class can be quickly obtained. Later, we will often use it when developing the Akka case.
Object name match { case Sample type 1(Field 1, Field 2, field n) => Expression 1 case Sample type 2(Field 1, Field 2, field n) => Expression 2 case Sample type 3(Field 1, Field 2, field n) => Expression 3 ... case _ => Expression 4 }
- In the parentheses after the sample type, the number of fields written should be consistent with that of the sample class
- When pattern matching is performed through match, the object to be matched must be declared as Any type
Example
//Case: pattern matching sample class object ClassDemo04 { //1. Create two sample classes Customer and Order //1.1 Customer includes name and age fields case class Customer(var name: String, var age: Int) //1.2 the order contains the id field case class Order(id: Int) def main(args: Array[String]): Unit = { //2. Define the objects of two case classes and specify them as Any type val c: Any = Customer("Sugar sugar", 73) val o: Any = Order(123) val arr: Any = Array(0, 1) //3. Match the two objects with patterns and print their member variable values respectively c match { case Customer(a, b) => println(s"Customer Object of type, name=${a}, age=${b}") case Order(c) => println(s"Order type, id=${c}") case _ => println("Unmatched") } } }
1.5 matching set
In addition to the above functions, pattern matching in Scala can also be used to match arrays, tuples, sets (lists, sets, mappings), etc.
Array(1,x,y) // Starting with 1, the following two elements are not fixed Array(0) // Elements that match only one 0 element Array(0, ...) // You can have any number, but start with 0
Example
//Case: pattern matching array object ClassDemo05 { def main(args: Array[String]): Unit = { //1. Define three arrays val arr1 = Array(1, 2, 3) val arr2 = Array(0) val arr3 = Array(1, 2, 3, 4, 5) //2. Find the specified array through pattern matching arr2 match { //Match: the length is 3, the first element is 1, and the last two elements don't matter case Array(1, x, y) => println(s"The matching length is 3, The first element is 1, The last two elements are: ${x}, ${y}") //Match: an array with only one 0 element case Array(0) => println("matching: An array with only one 0 element") //Match: the first element is 1, and the following elements are indifferent arrays case Array(1, _*) => println("matching: The first element is 1, An array whose trailing elements don't matter") //Other check items case _ => println("Unmatched") } } }
List(0) // Save 0 a list of only one element List(0,...) // The number of lists starting with 0 is not fixed List(x,y) // A list that contains only two elements
//Case: matching list of pattern matching object ClassDemo06 { def main(args: Array[String]): Unit = { //1. Definition list var list1 = List(0) var list2 = List(0, 1, 2, 3, 4, 5) var list3 = List(1, 2) //2. Pattern matching through match //Idea 1: implement it through List() list1 match { case List(0) => println("matching: List with only one 0 element") case List(0, _*) => println("matching: 0 start, The following elements don't care about the list") case List(x, y) => println(s"matching: A list of only two elements, Element is: ${x}, ${y}") case _ => println("Unmatched") } //Idea 2: use keywords to optimize nil and tail list1 match { case 0 :: Nil => println("matching: List with only one 0 element") case 0 :: tail => println("matching: 0 start, The following elements don't care about the list") case x :: y :: Nil => println(s"matching: A list of only two elements, Element is: ${x}, ${y}") case _ => println("Unmatched") } } }
Match Yuanzu
(1, x, y) // A tuple of three elements starting with 1 (x, y, 5) // There are three elements, and the last element is a tuple of 5
Example
//Case: matching tuple of pattern matching object ClassDemo07 { def main(args: Array[String]): Unit = { //1. Define two tuples val a = (1, 2, 3) val b = (3, 4, 5) val c = (3, 4) //2. Match the specified elements through pattern matching a match { case (1, x, y) => println(s"matching: Length 3, Start with 1, The last two elements have no tuples, Here are the last two elements yes: $ {x}, ${y}") case (x, y, 5) => println(s"matching: Length 3, End with 5, The first two elements don't matter, Here are the first two elements yes: $ {x}, ${y}") case _ => println("Unmatched") } } }
1.6 pattern matching in variable declaration
When defining variables, you can use pattern matching to quickly obtain data. For example, quickly obtain data from arrays and lists
Example
//Case: demonstrate pattern matching in variable declaration object ClassDemo08 { def main(args: Array[String]): Unit = { //1. Generate an array containing 0-10 numbers, and use pattern matching to obtain the second, third and fourth elements respectively //1.1 generate an array containing 0-10 numbers val arr = (0 to 10).toArray //1.2 use pattern matching to obtain the second, third and fourth elements respectively val Array(_, x, y, z, _*) = arr; //1.3 print results println(x, y, z) println("-" * 15) //2. Generate a list containing 0-10 numbers, and use pattern matching to obtain the first and second elements respectively //2.1 generate a list containing 0-10 numbers, val list = (0 to 10).toList //2.2 use pattern matching to obtain the first and second elements respectively //Idea 1: List() implementation val List(a, b, _*) = list //Idea 2: tail implementation val c :: d :: tail = list //2.3 print results println(a, b) println(c, d) } }
1.7 match for expression
Scala can also use pattern matching to match for expressions, so as to quickly obtain the specified data and make our code look more concise and elegant
Example
//Case: for expression for pattern matching object ClassDemo09 { def main(args: Array[String]): Unit = { //1. Define variables to record the student's name and age val map1 = Map("Zhang San" -> 23, "Li Si" -> 24, "Wang Wu" -> 23, "Zhao Liu" -> 26) //2. Obtain information about all students aged 23 //2.1 format 1: realized by if statement for ((k, v) <- map1 if v == 23) println(s"${k} = ${v}") //Split line println("-" * 15) //2.2 format 2: realized by fixed value for ((k, 23) <- map1) println(k + " = 23") } }
2. Option type
2.1 general
In actual development, it is inevitable to encounter null pointer exception when returning some data. It is relatively cumbersome to deal with it once. In Scala, when we return some data, we can return an object of Option type to encapsulate specific data, so as to effectively avoid null pointer exception.
In Scala, the Option type represents an optional value. There are two forms of this type of data:
-
Some(x): represents the actual value
-
None: indicates no value
be careful: use getOrElse Method when the value is None You can specify a default value.
Example
//Case: demonstrating Option types object ClassDemo10 { //1. Define a method to divide two numbers, and use Option type to encapsulate the result def div(a: Int, b: Int) = { if (b == 0) { None //Divisor 0, no result } else { Some(a / b) //If the divisor is not 0, the specific result will be returned } } def main(args: Array[String]): Unit = { //2. Then use pattern matching to print the results val result = div(10, 0) //Idea 1: print the results through pattern matching result match { //Not divide by zero, print the result case Some(x) => println(x) //Divide by zero printing exception error case None => println("Divisor cannot be 0") } println("-" * 15) //Idea 2: it is implemented by getOrElse() method println(result.getOrElse(0)) } }
3. Partial function
3.1 definitions
Partial functions provide A more concise syntax and simplify the definition of functions. With the functional programming of set, the code can be more elegant. The so-called partial function refers to A group of case statements wrapped in curly braces without match. The partial function is an instance object of PartialFunction[A, B], where A represents the input parameter type and B represents the return result type
3.2 format
val Object name = { //The pair of braces and a set of case statements inside them form a partial function case Value 1 => Expression 1 case Value 2 => Expression 2 case Value 3 => Expression 3 ... }
Example
//Case: demonstration of partial function object ClassDemo11 { def main(args: Array[String]): Unit = { //1. Define a partial function and return it according to the specified format val pf: PartialFunction[Int, String] = { case 1 => "one" case 2 => "two" case 3 => "three" case _ => "other" } //2. Call method println(pf(1)) println(pf(2)) println(pf(3)) println(pf(4)) } }
3.4 example 2: combined with map function
Example
//Case: partial function use, combined with map function object ClassDemo12 { def main(args: Array[String]): Unit = { //1. Define a list containing numbers from 1 to 10 val list1 = (1 to 10).toList //Core: use partial function combined with map for pattern matching val list2 = list1.map { //2 please convert all numbers from 1-3 to [1-3] case x if x >= 1 && x <= 3 => "[1-3]" //3 please convert the numbers from 4-8 to [4-8] case x if x >= 4 && x <= 8 => "[4-8]" //4 convert other numbers to (8 - *] case _ => "(8-*]" } //5. Print results println(list2) } }
4. Regular expression
4.1 General
The so-called regular expression refers to the correct formula that conforms to specific rules. It is an independent language and can be compatible with most programming languages. In scala, regular expressions can be easily used to match data. The details are as follows:
- Regex class is provided in Scala to define regular expressions
- To construct a Regex object, simply use the r method of the String class
- It is recommended to use three double quotation marks to represent the regular expression, otherwise you will have to escape the backslash in the regular expression
4.2 format
val Regular object name = """Specific regular expressions""".r be careful: use findAllMatchIn Method can obtain all regular matching data(character string).
Example
//Case: check whether the mailbox is legal object ClassDemo13 { def main(args: Array[String]): Unit = { //Requirement: define a regular expression to match whether the mailbox is legal //1. Define a string to represent the mailbox val email = "qq12344@163.com" //2. Define a regular expression to verify the mailbox /* . Represents any character + Quantifier, which means that the preceding character appears at least once, and it doesn't matter at most @ It must be a @ symbol and has no special meaning \. Because. Has a special meaning in regular, it needs to be transferred to make it ordinary */ val regex = """.+@.+\..+""".r //3. Print results if (regex.findAllMatchIn(email).size != 0) { //Legal mailbox println(s"${email} It's a legal mailbox!") } else { println(s"${email} It's an illegal mailbox!") } } }
Example 2
//Case: filter all illegal mailboxes object ClassDemo14 { def main(args: Array[String]): Unit = { //1. Define the list and record the mailbox val emlList = List("38123845@qq.com", "a1da88123f@gmail.com", "zhansan@163.com", "123afadff.com") //2. Define regular expressions val regex = """.+@.+\..+""".r //3. Get all illegal mailboxes through the filter val list = emlList.filter(x => regex.findAllMatchIn(x).size == 0) //4. Print results println(list) } }
Example 3
//Case: get the mailbox operator object ClassDemo15 { def main(args: Array[String]): Unit = { //1. Define the list and record the mailbox val emlList = List("38123845@qq.com", "a1da88123f@gmail.com", "zhansan@163.com", "123afadff.com") //2. Define regular expressions val regex = """.+@(.+)\..+""".r //3. Match all legal mailboxes and their corresponding operators according to pattern matching val result = emlList.map { //email is every element in the EML list //company means: what you enclose in a regular expression with (), that is, grouped data case email @ regex(company) => email -> s"${company}" case email => email -> "Unmatched" } //4. Print results println(result) } }
5. Exception handling
format
try { //Code that may cause problems } catch{ case ex:Exception type 1 => //code case ex:Exception type 2 => //code } finally { //code }
- The code in try is the business processing code we write
- catch indicates the code to be executed when an exception occurs
- In finally, you write code that will execute regardless of whether an exception occurs or not
Example
//Case: demonstrate exception handling object ClassDemo16 { def main(args: Array[String]): Unit = { //1. Use try.catch to handle the exception that divisor is zero try { //Possible problem code val i = 10 / 0 } catch { //Solutions to problems //Case ex: exception = > println ("something's wrong with the code!") case ex: Exception => ex.printStackTrace() } println("Hello!") println("-" * 15) //I am the dividing line //2. Throw an exception object throw new Exception("I am a Bug!") println("Hello, Scala!") //This line of code will not be executed } }
6. Extractor
Overview we have used the very powerful pattern matching function in Scala before. Through pattern matching, we can quickly obtain the member variable values in the sample class object.
For example:
// 1. Create two sample classes case class Person(name: String, age: Int) case class Order(id: String) def main(args: Array[String]): Unit = { // 2. Create a sample class object and assign it to Any type val zhangsan: Any = Person("Zhang San", 20) val order1: Any = Order("001") // 3. Use the match...case expression for pattern matching // Get member variables in the sample class order1 match { case Person(name, age) => println(s"full name: ${name} Age: ${age}") case Order(id1) => println(s"ID Is: ${id1}") case _ => println("Unmatched") } }
The answer is: No. If a class wants to support pattern matching, it must implement an extractor.
1. Extractor means unapply()method . 2. The sample class is implemented automatically apply(),unapply()method, We don't need to define it manually.
6.2 format
To implement a class extractor, you only need to implement an unapply method in the associated object of the class.
def unapply(stu:Student):Option[(Type 1, Type 2, Type 3...)] = { if(stu != null) { Some((Variable 1, Variable 2, Variable 3...)) } else { None } }
6.3 examples
object ClassDemo17 { //1. Create a Student class that contains two fields: name and age class Student(var name: String, var age: Int) //2. Implement a class extractor, use match expression for pattern matching, and extract the fields in the class. object Student { //Companion object def apply(name: String, age: Int) = new Student(name, age) //Free new def unapply(s: Student): Option[(String, Int)] = { //It is equivalent to disassembling an object into its properties if (s != null) Some(s.name, s.age) else None } } //Main method, as the main entry of the program def main(args: Array[String]): Unit = { //3. Create the object of Student class val s = new Student("Sugar sugar", 73) //Create objects in the normal way val s2 = Student("Sugar sugar", 73) //No new, create object, apply method guarantee //4. Print the attribute value of the object println(s2.name + "..." + s.age) //Get the property value of the object in the normal way //5. Get the method in the object through the extractor val result = Student.unapply(s2) println(result) } }