The foreword 0.

Type checking and conversions are implemented in every language, such as Instanceof and isInstance in Java, as well as Scala, but Scala has powerful pattern matching to simplify development. The principle of switch-case is similar to Java, but its matching ability is stronger. It can not only match values and types, but also can match classes and prefix classes. The Spark source code makes extensive use of pattern matching. Starting with type checking and conversion, this article introduces some common pattern matching and its use in Scala.

1. Type check

To test whether an object belongs to a given class, use the isInstanceOf method. If the test is successful, you can use the asInstanceOf method for the class conversion.

if(p.isInstanceOf[Employee]) {The type of s is converted to Employee
val s = p.asInstanceOf[Employee]}Copy the code

There are several main points to note about type conversions:

  • P.isinstanceof [Employee] will succeed if P points to an object of the Employee class and its subclasses.

  • If p is null, p.isinstanceof [Employee] will return false and p.asinstanceof [Employee] will return NULL.

  • If p is not an Employee, p.asinstanceof [Employee] will throw an exception.

  • If you want to test that p refers to an Employee object but is not a subclass, you can use: if(p.gettclass == classOf[Employee])

The classOf method is defined in the Scala.predef object and is therefore automatically introduced. However, pattern matching is usually a better choice than type checking and conversions.

p match{
// handle s as Employee
case s: Employee => ...
//p is not the Employee case
case_ = >... }Copy the code

2. Pattern matching

In Scala, pattern matching supports the following types of matching: value matching, type matching, collection element matching, tuple matching, and value or no value matching. Let’s look at how these types of matching are used from the perspective of code.

variablematch {
  caseXx => code}Copy the code

Unlike Java, there is no need to specify break, which has the effect of breaking. The default value is represented by the placeholder _, and match has the same return value as if.

2.1 value matches

Value matching, which is like integer, character, or string matching in Java. But it is guarded matching (which is understood as conditional matching by default)

// Character match
def main(args: Array[String) :Unit = {
  val charStr = '6'
  charStr match {
    case '+' => println("Matches the plus sign.")
    case '-' => println("Matches the minus sign.")
    case '*' => println("Matched the multiplication sign.")
    case '/' => println("Matched the division sign.")
    // Note: If all the above conditions are not met, execute the following code
    case _ => println("None of them match. I'm the default.")}}// String matching
def main(args: Array[String) :Unit = {
  val arr = Array("hadoop"."zookeeper"."spark")
  val name = arr(Random.nextInt(arr.length))
  name 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("I don't know you...")}}// Guard matching
def main(args: Array[String) :Unit = {
  / / guard type
  val character = '*'
  val num = character match {
    case= > '+'1
    case'-' = >2
    case _ if character.equals('*') => 3
    case_ = >4
  }
  println(character + "" + num)
} 
Copy the code

2.2 Type Matching

Java cannot do this. The matching format is as follows: case Variable name: type. The variable name can be replaced by _

// Type match
  def typeMathc (x: Any) = {
    x match {
      case_ :String => println("String")
      case_ :Int => println("Plastic")
      case_ :Array[Int] => println("Positive star array")
      case _ => println("nothing")}}Copy the code

2.3 Matching arrays, tuples, sets

Unlike type matching, which can match only the whole large type, type matching can match something like a certain class, but it can limit the elements of the matching class

// Array pattern matches
  def arrayMatch(x: Array[Int]) = {
    x match {
      case Array(1,x,y) => println(x + ":" + y)
      case Array(1) => println("only 1 ....")
      case Array(1,_*) => println("One")
      case _ => println("nothing....")}}//list pattern matches
  def listMatch() = {
    val list = List(3.- 1)
    // Pattern matching for List lists is similar to Array, but requires the list-specific :: operator
    // The two basic units for constructing List lists are Nil and ::, where Nil represents an empty List
    //tail returns a list of elements other than the first
    // Matches a list with a specified number of elements, a list with a specified element, and a list starting with an element
    list match {
      case x :: y :: Nil => println(s"x: $x y: $y")
      case 0: :Nil => println("only 0")
      case 1 :: _ => println("1...")
      case _ => println("something else")}}// Tuple match
  def tupleMatch() = {
    val tuple = (5.3.7)
    tuple match {
      case (1, x, y) => println(s"1, $x.$y")
      case (_, z, 5) => println(z)
      case _ => println("else")}}Copy the code

When no values are written to the array, the following matches are equivalent, with any argument equal to a full type match

case Array(_*) => println("*")
case_ :Array[Int] => println("Entire array")
Copy the code

2.4 Example Class Matching

Case Class sample classes are special classes in Scala. When the sample class is declared, the following things happen automatically:

  • The arguments received by the main constructor usually do not require explicit var or val qualifiers; Scala uses val qualifiers automatically

  • A companion object is automatically defined for the sample class and the apply method is provided to construct the corresponding object without the new keyword

  • The toString, equals, hashCode, and copy methods are generated unless the definitions of these methods are shown

  • It inherits both Product and Serializable, meaning that the sample class can be serialized and the methods of Product can be applied

Case class is multi-instance, followed by the construction of parameters, case Object is singleton.

In addition, case Class sample classes can add methods and fields and can be used for pattern matching. How to understand the pattern matching of the sample class? When using dynamic binding, the inheritance of the sample class can determine whether an object belongs to a subclass object, and the interface to the parent class can simplify the programming design. Similar to isInstanceOf in Part 1, the sample class can also accept input parameters for corresponding subclass operations.

class Amount
// Define the sample class Dollar, which inherits the Amount parent class
case class Dollar(value: Double) extends Amount
// Define a sample class Currency that inherits the Amount parent class
case class Currency(value: Double, unit: String) extends Amount
// Define the sample object Nothing, which inherits the Amount parent class
case object Nothing extends Amount
object CaseClassDemo {
  def main(args: Array[String) :Unit = {
    judgeIdentity(Dollar(10.0))
    judgeIdentity(Currency(20.2."100"))
    judgeIdentity(Nothing)}// Custom method, pattern matching to determine the AMT type
  def judgeIdentity(amt: Amount) :Unit = {
    amt match {
      case Dollar(value) => println(s"$value")
      case Currency(value, unit) => println(s"Oh noes,I got $unit")
      case_ :Currency => println(s"Oh noes,I go")
      case Nothing => println("Oh,GOD!")}}}Copy the code

2.5 Yes Value No Value Matching

The Scala Option Option type is used to indicate that a value is optional, with or without a value. Option[T] is a container of optional values of type T, which can be obtained by the get() function. Option[T] is a Some if the value exists. If not, Option[T] is the object None. Option is usually used in conjunction with pattern matching to determine whether a variable has a value or no value.

  val grades = Map("jacky" -> 90."tom" -> 80."jarry" -> 95)
  def getGrade(name: String) :Unit = {
    val grade: Option[Int] = grades.get(name)
    grade match {
      case Some(grade) => println("Result:" + grade)
      case None => println("No such person!")}}def main(args: Array[String) :Unit = {
    getGrade("jacky")
    getGrade("Zhang")}Copy the code

3. Summary

Pattern matching in Scala is used to simplify code, to achieve more powerful uncertain or deterministic matches, and to customize pattern matching, which automatically uses the Apply and unapply methods. Check your profile for more.