Scala learning notes

Posted by sunnypal on Thu, 03 Feb 2022 10:47:57 +0100

1. Introduction to Scala

1.1 general

Scala is a multi paradigm programming language based on JVM. Generally speaking, Scala is a functional object-oriented language running on the JVM. Scala can be widely used in various programming tasks. It can do everything from writing small scripts to building giant systems. Because of this, Scala can provide some outstanding features, such as its integration of various features of face-to-face object programming and function oriented programming, as well as a higher-level concurrency model.

JVM based explanation: Scala running environment is similar to Java and depends on JVM

Multi paradigm interpretation: Scala supports multiple programming styles

1.2 language features

Scala is object-oriented

Scala is a pure object-oriented language, and every value is an object. The data type and behavior of objects are described by classes and features. The extension of class abstraction mechanism is realized in two ways, one is subclass inheritance, the other is mixing mechanism. Both of these two ways can avoid the problem of multiple inheritance.

Scala is functional programming

Scala is also a functional language whose functions can be used as values.

Scala is compatible

Compatible with Java, you can access the huge Java class library

Scala is lean

Scala has strong expressive ability. One line of code is equal to multiple lines of Java code. It has fast development speed, which can keep your program short and clear, and look more concise and elegant

Scala is statically typed

Scala has a very advanced static type system, which ensures the security and consistency of the code through compile time inspection. Support: type inference and pattern matching

Scala can develop large instructional applications

For example: Spark, Flink program, etc

 

1.3 comparison between Scala program and Java program

1.3.1 comparison of procedure execution

 

1.3.2 code comparison

Java code

// Entity class
public class People {

    private String name;
    private int age;
    public People(){}

    public People(String name, int age) {
        this.name = name;
        this.age = age;

    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;

    }

    public void setAge(int age) {
        this.age = age;
    }

}

// Test class
public class CodeDemo {

    public static void main(String[] args) {
        People people = new People("wang",20);
        System.out.println(people);
    }

}

Scala code

case class People(var name:String, var age:Int)
val peolpe = People("wang",20);
println(peolpe);

1.4 construction of scala environment

1.4.1 general

Scala is based on Java and uses a lot of Java class libraries and variables. There must be a Java running environment for Scala to execute correctly. To compile and run Scala programs, you need to:

JDK

Scala compiler (Scala SDK)

Next, you need to install the following in sequence:

1. Install JDK

2. Install Scala SDK

3. Install Scala plug-in in IDEA

1.4.2 installing JDK

Install jdk1 8 64 bit version, and configure the environment variables. This process is omitted.

1.4.3 installing the Scala SDK

The Scala SDK is a compiler for the Scala language. To develop Scala programs, you must first install the Scala SDK. Installation steps (example version: scala -2.11.12):

1. Download the Scala SDK

Official download address: https://www.scala-lang.org/download/

2. Install Scala SDK

2.1 double click scala - 2.11.12 MSI, install scala in the specified directory and install it as a fool. Next, next

2.2 the installation path should be legal, and there should be no special symbols such as Chinese, spaces and so on

3. Test whether the installation is successful

3.1 open the console and enter: scala - version

Scala code runner version 2.11.12 -- Copyright 2002-2017, LAMP/EPFL

3.2 start the scala interpreter, enter Scala, and verify the execution results of scala code in 1.3.2

3.3 exit the Scala interpreter, enter: quit or close the console directly

1.4.4} install IDEA Scala plug-in

IDEA does not support Scala program development by default, so you need to install Scala plug-in in IDEA to support Scala language.

First download the specified version of IDEA Scala plug-in:

  1. The downloaded Scala plug-in must be consistent with the locally installed version of IDEA
  2. Official download address: https://plugins.jetbrains.com/plugin/1347-scala

Then configure the Scala plug-in in the IDEA

Open file settings, and there is an Install plugin from disk on the plugins tab

Find the downloaded plug-in, click OK, and restart IDEA

 

2.Scala syntax

2.1 output statement

Mode 1: line feed output

Format: println(Statements printed to the console)

Mode 1: output without line break

Format: print(Statements printed to the console)

Note: whether println() or print(), multiple values can be printed at the same time. The format is: Print (value 1, value 2, value 3...)

2.2 semicolon

For Scala statements, the semicolon after a single line of code can be written or not written. If multiple lines of code are written on one line, the semicolon in the middle cannot be omitted, and the semicolon of the last code can be omitted or not written.

Example:

println(123)
println(456);println(789)

2.3 declaration of variables

Format:

Java variable definition

int a = 0;

Variables defined in Scala have two keywords: val and var

val/var Variable name : Variable type = Initial value

Of which:

val defines variables that cannot be re assigned, that is, user-defined constants

var defines a variable that can be re assigned

Scala uses constants rather than variables to solve problems. The advantage of this is that it can reduce the safety problems of multithreading concurrency, which is especially suitable for multi concurrency and distributed scenarios.

Scala supports automatic type inference, which can automatically infer the type of variable according to the value of variable, making the code more concise.

Reference code:

scala> val name = "zhangsan"
name: String = zhangsan
scala> val age = 20
age: Int = 20

2.4 string

Scala provides a variety of ways to define strings

2.4.1 double quotation marks

Syntax:

val/var Variable name =  ""String"

2.4.2 interpolation expression

In Scala, interpolation expressions can be used to define strings, effectively avoiding the splicing of a large number of strings

Syntax:

val/var Variable name = s"${variable/expression}"String"

explain:

·Add s before defining string

·In a string, ${} can be used to reference variables or write expressions

Example:

scala> val str1 = "a"
str1: String = a

scala> val str2 = "b"
str2: String = b

scala> val result = s"str1=${str1},str2=${str2}"
result: String = str1=a,str2=b

2.4.3 three quotation marks

Use three quotation marks to define a string to save a large piece of text, which can include any character without escape

Syntax:

val/var Variable name =  """String ''

Example:

Define a string and save the following SQL statement

select * from scala_customer where id = 1

Using Java definitions

String sql = "select \n" +
                "\t\t* \n" +
                "from \n" +
                "\t\tscala_customer \n" +
                "where \n" +
                "\t\tid = 1";
System.out.println(sql);

Using Scala definitions

val sql = """select
                | *
                |from
                | scala_customer
                |where
                | id = 1"""
println(sql)

2.5 identifier

Identifier concept

The character sequence used by Scala in naming various variables, methods and functions is called identifier.

Any place where you can name yourself is called an identifier.

Naming rules for identifiers

The identifier declaration in Scala is basically the same as that in Java, but the details will change.

1) The first character is a letter, the following characters are any letters and numbers, dollar symbol, and can be followed by underscore_

2) Number cannot start

3) The first character is an operator (such as + - * /), and the subsequent characters also need to be followed by an operator, at least one

4) Operators (such as + - * /) cannot be in the middle and last of identifiers

5) Any string that can be included with backquotes (` `), even keywords

Identifier naming considerations

Package name: try to adopt meaningful package name, short and meaningful

Hump method is adopted for variable name, function name and method name.

"$" and "" It is best not to appear in identifiers. The "$" character is also treated as a letter, but is retained as an identifier generated by the scala compiler. The identifier in the user program should not contain the "$" character. Although it can be compiled, it may cause name collision with the identifier generated by the scala compiler.

”_” It has important uses in Scala to prevent "" The usage is confused, and it is generally not used for variable declaration.

Example:

val ++ = "123"
val %@!#~ = "345"
val `public` = ""

2.6 data type

Data class

describe

Byte

8-bit signed complement integer. The range of values is - 128 to 127

Short

16 bit signed complement integer. The range of values is - 32768 to 32767

Int

32-bit signed complement integer. The range of values is - 2147483648 to 2147483647

Long

64 bit signed complement integer. The range of values is - 9223372036854775808 to 9223372036854775807

Float

32-bit, IEEE 754 standard single precision floating-point number

Double

64 bit IEEE 754 standard double precision floating point number

Char

16 bit unsigned Unicode character with interval value of U+0000 to U+FFFF

String

Character sequence

Boolean

true or false

Hierarchy chart

 

type

describe

Any

Any is a supertype of all types, also known as a top-level type. It defines some general methods, such as equals, hashCode and toString.

AnyVal

Parent of all numeric types

AnyRef

Parent class of all object types (reference types)

Unit

Indicates no value, which is equivalent to void in other languages. The result type used as a method that does not return any results. Unit has only one instance value, written as ().

Null

Null is a subclass of AnyRef. Its instance is null. Null can be assigned to any object type.

Nothing

Nothing type is at the bottom of Scala's class hierarchy; It is a subtype of any other type.

 

2.7 operators

In Scala, operators are methods. Scala contains the following types of operators:

Arithmetic operator

Relational operator

Logical operator

Bitwise Operators

Assignment Operators

2.7.1 arithmetic operators

operator

operation

example

result

+

Plus sign

+3

3

-

minus sign

b=4; -b

-4

+

plus

5+5

10

-

reduce

6-4

2

*

ride

3*4

12

/

except

5/5

1

%

Mold taking (residual)

7%5

2

+

String addition

"He"+"llo"

"Hello"

Unlike Java, Scala does not have + + - these two operators, which can achieve the same effect through + =, - =.

2.7.2 relational operators

operator

Operation

example

result

==

Equal to

4==3

FALSE

!=

Not equal to

4!=3

TRUE

<

less than

4<3

FALSE

>

greater than

4>3

TRUE

<=

Less than or equal to

4<=3

FALSE

>=

Greater than or equal to

4>=3

TRUE

The difference between Java and Scala about = =

Requirement description

Scala code

Java code

Comparative data

==Or=

equals() method

Compare references

eq method

==Or=

Example:

val s1 = "abc"
val s2 = new String("abc")
println(s1 == s2)
println(s1.eq(s2))

2.7.3 logical operators

It is used to connect multiple conditions (generally speaking, it is a relational expression), and the final result is also a Boolean value.

Assumption: variable A is true and variable B is false

operator

describe

example

&&

Logic and

(A & & B) operation result is false

||

Logical or

(a | b) the operation result is true

!

Logical non

! (A & & B) operation result is true

be careful:

In Scala code, you cannot continuously negate the value of a Boolean type, but you can do so in Java.

Namely: println(!!true)

This writing will report an error. This writing method is not supported.

2.7.4 assignment operator

Assignment operator is to assign the value of an operation to a specified variable.

operator

describe

example

=

A simple assignment operator assigns the value of an expression to an lvalue

C = A + B , assign the result of A + B expression to C

+=

Add and assign

C += A equals C = C + A

-=

Assign value after subtraction

C -= A equals C = C - A

*=

Multiply and assign

C *= A equals C = C * A

/=

Assign value after division

C /= A equals C = C / A

%=

Assign value after remainder

C% = a equals C = C% a

<<=

Left shift assignment

C < < 2 equals C = C < < 2

>>=

Assignment after shift right

C > > = 2 equals C = C > > 2

&=

Bitwise and post assignment

C & = 2 equals C = C & 2

^=

Assignment after bitwise XOR

C ^= 2 equals C = C ^ 2

|=

Bitwise or post assignment

C |= 2 equals C = C | 2

2.7.5 bitwise operators

operator

describe

example

&

Bitwise and operator

(A & B) output result 12, binary interpretation: 0000 1100

|

bitwise or operator

(a | b) output result 61, binary interpretation: 0011 1101

^

bitwise exclusive or operator

(a ^ b) output result 49, binary interpretation: 0011 0001

~

Bitwise negation operator

(~ a) output result - 61, binary interpretation: 1100 0011, in the complement form of a signed binary number.

<<

Move left operator

A < < 2 output result 240, binary interpretation: 1111 0000

>>

Move right operator

A > > 2 output result 15, binary interpretation: 0000 1111

>>>

unsigned right shift

A > > > 2 output result 15, binary interpretation: 0000 1111

2.8 process control and circulation

2.8.1 if condition judgment

matters needing attention:

  1. In scala, the if else statement has a return value, which is the last line in the code block
  2. In scala, the return keyword is not required for return values of methods, functions and condition judgment
  3. There is no ternary expression in scala. You can use if expression instead of ternary expression

Example:

object Example5 {

  def main(args: Array[String]): Unit = {
    val num = 21
    val name = if (num > 20) "Xiao Ming" else "Xiao Hong"
    println("name=>" + name)

    // If the type of the returned value in the if else statement is different, scala will automatically infer the common type of the two as the variable type
    //Any
    val name2 = if (num == 20) "Xiao Ming" else 99
    println("name2=>" + name2)
    println("name2.getClass=>" + name2.getClass)

    //If the else statement block is missing from the if else {statement, the default is Unit, which is represented by (), similar to void in java
    val name3 = if (num > 20) "Xiao Ming"
    val name4 = if (num > 20) "Xiao Ming" else ()
    println(name3)
    println(name4)

  }

}

2.8.2 for loop

2.8.2.1 simple cycle

Format:

for(i <- expression/array/aggregate){
    //Logic code
}

Reference code:

object Example7 {

  def main(args: Array[String]): Unit = {
    //Using the to method will produce a continuous interval range [0-10], which is contained on both sides
    for (i <- 0 to 10) {
      println("i=>" + i) // 0 - 10
    }

    //Using the until method will produce a continuous interval range [0-10], excluding 10
    for (i <- 0 until 10) {
      println("i=>" + i) //  0 - 9
    }

    //Traversal string
    for (s <- "xiaoming") {
      println(s)
    }
  }

}

2.8.2.2 nested loops

Traditional way

for (i <- 1 to 3){
    for (j <- 1 to 5) if (j==5) println("*") else print("*")
}

Scala specific approach

for (i <- 1 to 3;j <- 1 to 5) if (j==5) println("*") else print("*")

2.8.2.3 guard

if judgment statements can be added to the for loop, which is called guard.

Syntax:
for(i <- expression/array/aggregate if expression){
    //Logic code
}

Reference code:

for (i <- 1 to 10 if (i % 3) == 0) println(i)    // i = 3,6,9

2.8.2.4 derivation for loop

In Scala, the for loop has a return value. In the body of the for loop, you can use the yield expression to build a set. The for expression that has used yield is called a derivation.

For each iteration of the for loop, the yield will generate a value, which will be recorded by the loop (in the internal implementation, it is like a buffer). When the loop ends, the set composed of all yield values will be returned, and the type of the returned set is consistent with the type of the traversed set.

For (e < - list (1,2,3)) {yield e * e} / / syntax error. Yield cannot be in any parentheses

Reference code:

var v = for(i <- 1 to 10) yield i * 10
println(v)

2.8.3 while cycle

The use of while and do while in Scala is basically the same as that in Java

2.8.4 break and continue

In Scala, the break and continue keywords similar to Java have been removed, and scala. Com is needed util. breakable and break() methods in Breaks class under control package

2.8.4.1 break usage

Guide Package

import scala.util.control.Breaks._

Wrap expressions with breakable

Add the break() method where you need to exit the loop

Reference code:

import scala.util.control.Breaks._
Breakable{

      for (i <- 1 to 10){
        if(i == 5) break() else println(i)
      }

}

2.8.4.2 continue usage

The implementation of continue is similar to break, but there are differences. The implementation of break is to wrap the whole expression with Breakable {}, while the implementation of continue is to wrap the loop body of the expression with Breakable {}.

Reference code:

import scala.util.control.Breaks._
for (i <- 1 to 10){
      breakable{
        if (i % 3 == 0 ) break()
        else println(i)
      }
}

2.9 methods and functions

Method format:

def Method name (Parameter name: parameter type, parameter name: parameter type) : return type = {
    //Method body
} 

The return value type can be omitted (the definition of recursive methods cannot be omitted), which is automatically inferred by the Scala compiler.

If there is a return value type, the return value of the last statement of the method must be consistent with the return value type of the method.

The return value can be left blank. The default value is the value of the {} expression.

Example:

def getMax(a:Int ,b:Int): Int = {
    if (a>b) a else b
}

2.9.1 method parameters

The method parameters in Scala are flexible. It supports the following types of parameters:

1. Default parameters

2. Named parameters

3. Variable length parameters

2.9.1.1 default parameters

Default values can be given to parameters when defining methods.

Reference code:

def getSum1(x:Int = 10 ,y:Int = 20) = {
    x + y
}

2.9.1.2 named parameters

When calling a method, you can specify the name of the parameter to call.

Reference code:

val sum = getSum1(y=1)

2.9.1.3 variable length parameters

If the parameters of a method are not fixed, the parameters of the method can be defined as variable length parameters.

Format:

def Method name (Parameter name: parameter type*) : return type = {
    //Method body
} 

2.9.2 method call

2.9.2.1 suffix adjustment usage

Syntax:

Object name.Method name (parameter)

Example:

Math.abs(-1)

2.9.2.2 infix tone usage

Syntax:

Object name method name parameter

Example:

Math abs -1

2.9.2.3 use of curly braces

Syntax:

Object name.Method name{
    //Expression 1
    //Expression 2
}

Example:

Math.abs{-1}

Method can only use curly braces for one argument

2.9.2.4 usage without parentheses

If the method has no parameters, you can omit the parentheses after the method name

Example:

def say() = println("hello")
say

2.9.3 function

Format:

val Variable name = (Parameter name: parameter type, parameter name: parameter type...) =>{
    // Function body
}

Example:

val f1 = (x:Int,y:Int) =>{
   x + y
}

2.9.4 difference between method and function

In java, there is no difference between methods and functions, but their names are different. In Scala, functions and methods are different:

1. In Scala, def statement is used to define methods and val statement is used to define functions.

2. In Scala, at runtime, the method is loaded into the method area of the JVM, and the function is loaded into the heap memory of the JVM.

3. The method cannot exist as a separate expression (except for methods with empty parameters), while the function can.

Example:

object Example14 {

  // Define a parameterized method
  def m(x:Int) = 2*x

  // Define a function
  val f = (x:Int) => 2*x

  // Define a parameterless method
  def m1()=1+2

  // A parameterized method cannot appear as a final expression
  m

  // Functions can appear as final expressions
  f

  // Parameterless methods can appear as final expressions
  m1

}

4. The method can have no parameter list, and the parameter list can also be empty. However, the function must have a parameter list (which can also be empty).

Example:

// Method can have no parameter list
def m2 = 100

//Method can have an empty parameter list
def m3() = 100

//The function must have a parameter list, otherwise an error is reported
var f1 =  => 100

//A function can also have an empty argument list
var f2 = () => 100

5. Method name means method call; But the function name only represents the function itself.

6. The method can be automatically (called ETA extension) or manually forced into a function; However, functions cannot be converted to methods

Convert method to function:

def m4( x : Int , y : Int ) = {
      x + y
}
val f4 = m4 _
println(f4 (1,2))

2.10 classes and objects

A class is an abstraction of an object, and an object is a concrete instance of a class. Classes are abstract and do not occupy memory, while objects are concrete and occupy storage space. Class is a blueprint for creating objects. It is a software template that defines methods and variables included in specific types of objects.

Create classes and objects in short form:

  1. If the class is empty and has no members, {} can be omitted
  2. If the constructor parameter is empty, you can omit ()

Example:

object Example15 {

  class People

  def main(args: Array[String]): Unit = {
    val p = new People
  }

}

2.10.1 member variables

You can use var/val to define the member variable, and the object is defined by {object name To access member variables.

Example:

object Example16 {

  class Person{
    var name = ""
    var age = 0
  }

  def main(args: Array[String]): Unit = {
    val person = new Person
    person.name = "Zhang San"
    person.age = 24
    print(s"full name: ${person.name},Age: ${person.age}")
  }

}

Initializing member variables with underscores

When defining member variables of var type, you can use_ Initialize member variables.

String->null
Int->0
Boolean->false
Double->0.0
...

Example:

object Example16 {
    var col1:String = _
    var col2:Byte = _
    var col3:Int = _
    var col4:Long = _
    var col5:Float = _
    var col6:Double = _
    var col7:Char = _
    var col8:Boolean = _
}

Member variables of type val must be initialized manually

2.10.2 access modifier

In Scala, there is no public keyword, and members that are not marked as private and protected are public.

The permission modifiers in Scala are only: private, private[this], protected, and default.

Class 2.10.3 constructor

2.10.3.1 main constructor

Syntax:

class Class name(var/val Parameter name:type = Default value,...){
    //Construct code block
}

explain:

The main constructor is intertwined with the class name. A class can only define one main constructor.

The order in which objects are created must be executed first by the main constructor.

The parameters of the main constructor become the field properties of the class.

In the main constructor parameters, parameters that are not modified by any keywords are private [this] by default

The code not contained in any method is the code of the main constructor.

Reference code:

object Example17 {

  class Person(var name:String = "Zhang San",var age:Int = 24){
    println("The main constructor was called")
  }

  def main(args: Array[String]): Unit = {

    //Empty parameter
    val p1 = new Person("Li Si",2)

    //Full reference
    val p2 = new Person()

    //Specify parameters
    val p3 = new Person(age = 2)

    println(s"p1:${p1.name},${p1.age}")
    println(s"p2:${p2.name},${p2.age}")
    println(s"p3:${p3.name},${p3.age}")
  }

}

2.10.3.2 auxiliary constructor

The auxiliary constructor method name defaults to this and cannot be changed. The first line of code of the auxiliary constructor must call the main constructor or other auxiliary constructors. The order of creating objects must be executed first by the main constructor.

Syntax:

def this(Parameter name:Type,...){
    //The first line needs to call the main constructor or another constructor
    //Constructor code
}

Example:

object Example18 {

  class Person {

    println("The main constructor was called")
    private var name = ""
    private var age = 0

    def this(name: String){
      this()  //Call the main constructor
      println("Auxiliary constructor called-")
      this.name = name
    }

    def this(name: String, age: Int){
      this(name)  //Call other auxiliary constructors
      println("Auxiliary constructor called--")
      this.age = age
    }

  }

  def main(args: Array[String]): Unit = {
    new Person("zs",20)
  }

}

2.10.4 single case object

There is no static keyword in Scala. If you want to define static variables and static methods similar to those in Java, you need to use the singleton object in Scala. A singleton object means that there is only one object in the world, which is also called an isolated object. Defining a singleton object is very similar to defining a class, that is, replacing class with object.

Its main functions:

1) Tool storage methods and constants

2) Efficiently share a single immutable instance

3) When a single instance is required to coordinate a service

Format:

object Singleton object name{}

The member variables defined in object are similar to static variables in Java. There is only one object in memory.

In the singleton object, the singleton object name can be used directly Call members in the same way.

Example:

object Example19 {

  object Dog{
    val leg_num = 4
    def say(): Unit = println("dog")
  }

  def main(args: Array[String]): Unit = {
    println(Dog.leg_num)
    Dog.say()
  }

}

2.10.5 associated objects

In Java or C + +, classes with both instance methods and static methods are usually used. In Scala, you can achieve the same goal through classes and companion objects with the same name as classes.

definition:

In the same scala class file, if the names of class and object are the same, then class is the associated class of object and object is the associated object of class.

be careful:

  1. Associated object and associated class names must be the same
  2. Companion objects and companion classes must be in the same Scala source file
  3. The associated object and associated class can access the private attribute of each other. If the permission is private[this], it can only be accessed in the current class, and the associated object cannot be accessed directly.

Reference code:

object Example21 {

  // Associated class
  class Person{
    def eat(): Unit = print("eat" + Person.food)
  }

  // Companion Object 
  object Person{
    private val food = "meal"
  }

  def main(args: Array[String]): Unit = {
    val person = new Person
    person.eat()
  }

}

2.10.6 succession

Syntax:

class/object Subclass extends Parent class{
}

Subclass override methods must use the override modifier.

You can override a val field with override, and the var field of the parent class cannot be overridden.

Example:

object Example22 {

  class Person{
    val name = ""
    var age = 24
    def say(): Unit = print("")
  }

  class Student extends Person{
    override val name = "sjh"
    override def say(): Unit = print("hello")
  }

  def main(args: Array[String]): Unit = {
    val student = new Student()
    student.say()//hello
  }

}

2.10.7 abstract classes

Format:

abstract class Abstract class name{
    val/var Abstract field name:type
    def Method name(parameter:Parameter type...):Return type
}

Example:

object Example23 {

  abstract class Shape{
    val c:Int
    def getArea:Double
  }

  class Square(x:Int) extends Shape{
    override val c: Int = x
    override def getArea: Double = c * c
  }

  class Circle(r:Int) extends Shape{
    override val c: Int = r
    override def getArea: Double = Math.PI * c * c
  }

  def main(args: Array[String]): Unit = {
    val square = new Square(1)
    println(square.getArea)//1
    val circle = new Circle(1)
    println(circle.getArea)//3.141592653589793
  }

}

2.10.8 sample class / sample object

2.10.8.1 sample class

Sample class is a special class, which is generally used to save data (similar to Java POJO). It is often used in concurrent programming, Spark, Flink and other frameworks.

Format:

case class Sample class name([var/val] Member variable name 1:Type 1...)

Example:

case class Person(val name:String, var age:Int)

If it is not written, the default modifier of the variable is val, which can be omitted.

If you want to realize that the value of a member variable can be modified, you need to manually add var modification.

Automatically create associated objects and implement some methods in it. The common methods are as follows:

apply() method

You can quickly use the class name to create objects, omitting the new keyword.

toString() method

Each attribute value of the object can be printed directly during printing.

For example: val p = Person()

equals() method

You can use = = directly to compare attribute values.

hashCode() method

The hash value of the same object must be the same, and the hash value of different objects is generally different.

copy() method

It can be used to quickly create instance objects with the same attribute value, and assign values to the specified member variables in the form of named parameters.

unapply() method

Implement the extractor and apply it to pattern matching.

2.10.8.2 sample object

The singleton object decorated with case is called a sample object, and it has no main constructor. It is mainly used in:

  1. enum
  2. As a message without any parameters

Example:

object ClassDemo {

  //Trait Sex, indicating gender
  trait Sex

  //Sample object, representing male, inheriting Sex traits
  case object Male extends Sex

  //Sample object, representing female, inheriting Sex traits
  case object Female extends Sex

  //Define the sample class Person
  case class Person(var name:String, var sex:Sex){}

  def main(args: Array[String]): Unit = {
    val p = Person("sjh", Male)
  }

}

2.11 characteristics

If we need to strengthen the functions of some classes (or objects) without affecting the current inheritance system, we need to put these unique functions into characteristics. The traits in Scala should be decorated with the keyword trait.

characteristic

Characteristics can improve the reusability of code.

Characteristics can improve the scalability and maintainability of code.

Classes and traits are inheritance relationships. Classes and classes only support single inheritance, and classes and traits can inherit single or multiple.

Scala can have common fields, abstract fields, common methods and abstract methods.

If the trait has only abstract content, such trait is called thin interface.

If a trait has both abstract content and concrete content, such a trait is called rich interface.

Syntax:

Defining traits

trait Trait name{
    //General field
    //Abstract field
    //Common method
    //Abstract method
}

Inherited traits

class Class name extends Trait 1 with Trait 2{
    //Override abstract field
    //Rewrite abstract methods
}

Reference code:

object Example25 {

  trait MsgSender{
    def send(msg:String)
  }

  trait MsgReceiver{
    def receive()
  }

  // Class inherits multiple traits
  class MsgWorker extends MsgSender with MsgReceiver{
    override def send(msg: String): Unit = println(s"Send message: $msg")
    override def receive(): Unit = println("receive messages")
  }

  // object inherits trait
  object MsgWorker extends MsgSender with MsgReceiver{
    override def send(msg: String): Unit = println(s"Send message: $msg")
    override def receive(): Unit = println("receive messages")
  }

  def main(args: Array[String]): Unit = {
    val worker = new MsgWorker
    worker.send("hello")
    worker.receive()
    MsgWorker.send("hello scala")
    MsgWorker.receive()
  }

}

Mix in object 11.2

Sometimes we want to temporarily enhance or expand the functions of objects without changing the class inheritance system. At this time, we can consider using object blending technology. The so-called object blending technology is that in scala, there is no inheritance relationship between classes and traits, but the class object can have members in the specified traits through specific keywords.

Syntax:

val/var Object name = new class with Idiosyncrasy

Reference code:

object Example26 {

  trait Logger{
    def log(): Unit = println("log..")
  }

  class User{
  }

  def main(args: Array[String]): Unit = {
    // val/var object name = new class
    val user = new User with Logger
    user.log()
  }

}

2.11.2 trait construction mechanism

Each trait has only one parameterless constructor, that is, trait also has construction code, but unlike classes, traits cannot have constructor parameters.

When one class inherits another class and multiple trait s, the constructor executes in the following order when creating an instance of this class:

Execute parent constructor

Constructor that executes trait from left to right

If a trait has a parent trait, execute the constructor of the parent trait first

If multiple traits have the same parent trait, the parent trait constructor is initialized only once

Execute subclass constructor

Reference code:

object Example27 {

  trait A{
    println("A")
  }

  trait B extends A{
    println("B")
  }

  trait C extends A{
    println("C")
  }

  class D{
    println("D")
  }

  class E extends D  with B with C{
    println("E")
  }

  def main(args: Array[String]): Unit = {
    new E//DABCE
  }

}

2.12 package

A package is a folder. Decorated with package, you can distinguish between duplicate name classes.

Format:

Format 1: document top marking method-Consolidated Edition
Package Package name 1.Package name 2.Package name 3

Format 2: document top marking method-Disassembled version
Package Package name 1.Package name 2
Package Package name 3

Format 3: concatenated package statement
Package Package name 1.Package name 2{
    Package Package name 3{
    }
}

Scope of package:

Child packages have direct access to the contents of the parent package.

When the upper layer accesses the lower content, it can be realized by importing or writing the full package name.

If the upper and lower layers have the same class, the principle of proximity shall be adopted when using (the lower layer is preferred).

Introduction of package:

scala introduces Java. Net by default Lang package, scala package and Predef package.

The introduction of packages is not limited to the top of Scala files, but can be written wherever needed.

If you need to import all classes and traits in a package, use underscores_ realization.

If multiple imported contain the same class, it can be solved by renaming or hiding.

Rename format:

import java.util.{HashSet => JavaSet}

Hide format:

import java.util.{HashSet => _,_}//Introduce classes other than HashSet under util package

 

2.13 pattern matching

Pattern matching is a mechanism to check whether a value matches a pattern. A successful matching will deconstruct the matching value into its components at the same time. It is an upgraded version of the switch statement in Java and can also be used to replace a series of if/else statements.

A pattern matching statement includes a value to be matched, a match keyword, and at least one case statement.

Match corresponds to the switch in Java, but it is written after the selector expression. That is: selector match {alternative}.

The match expression completes the calculation by trying each pattern in the order of coding. As long as a matching case is found, the remaining cases will not continue to match.

match..case and switch Case differences

Java writing

switch(n) {
  case(1): ...; break;
  case(2): ...; break;
  default: ...;
}

In Scala, you don't need to write break at the end of each time_ Equivalent to default

n match {
  case "a" | "b" => ...
  case "c" => ...
  case _ => ...
}

2.13.1 simple pattern matching

Format:

variable match{
    case Constant 1 => Expression 1
    case Constant 2 => Expression 2
    case Constant 3 => Expression 3
    case _ => Expression 4     //Default item
}

Example:

def main(args: Array[String]): Unit = {
    println("Enter a word")
    val word = StdIn.readLine()
    word 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")
    }
}

2.13.2 type matching

In addition to matching data, matcha expressions can also perform type matching. If we want to execute different logic according to different data types, we can use match expression to implement it.

Format:

Object name match{
    case Variable name 1:Type 1 => Expression 1
    case Variable name 2:Type 2 => Expression 2
    case _:Type 3 => Expression 3    //The expression does not use the variable name. You can use the underscore instead
    case _ => Expression 4          //Default item
}

Example:

def main(args: Array[String]): Unit = {
    val a:Any = "hadoop"
    a match {
        case x:String => println(s"${x}Is a string")
        case x:Int => println(s"${x}It's a number")
        case _ => println("Unmatched")
    }
}

2.13.3 guard

Guard refers to adding if condition judgment in case, which can make the code more concise.

Format:

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 //Default item
}

Example:

def main(args: Array[String]): Unit = {
  val a = StdIn.readInt()
  a match {
    case x if x > 0 => println("Positive number")
    case x if x < 0 => println("negative")
    case _ => println("Is 0")
  }
}

2.13.4 sample class matching

In Scala, pattern matching can be used to match the sample class, so that the member data in the sample class can be obtained quickly.

Format:

Object name match{
    case Sample type 1(Field 1, Field 2..) => Expression 1
    case Sample type 2(Field 1, Field 2..) => Expression 2
    case Sample type 3(Field 1, Field 2..) => Expression 3
    case _ => Expression 4 //Default item
}

Example:

object ClassDemo {

  case class Customer(name:String, age:Int)
  case class Order(id:Int)

  def main(args: Array[String]): Unit = {
    val a:Any = Customer("sjh", 20)
    a match {
      case Customer => println("yes customer")
      case Order => println("yes order")
      case _ => println("Unmatched")
    }
  }

}

2.13.5 set matching

Matching array example

def main(args: Array[String]): Unit = {

  //Define three arrays
  val arr1 = Array(1, 2, 3)
  val arr2 = Array(0)
  val arr3 = Array(0 , 1, 2, 3,4)

  arr1 match {
    case Array(1, _, _) => println("The length is 3 and the first element is 1")
    case Array(0) => println("Length 1, element 0")
    case Array(0, _*) => println("First element 0, any other element")
  }

}

Match list example

def main(args: Array[String]): Unit = {

    //Define three lists
    val list1 = List(1, 2, 3)
    val list2 = List(0)
    val list3 = List(0, 1, 2, 3,4)

    list3 match {
        case List(1, _, _) => println("The length is 3 and the first element is 1")
        case List(0) => println("Length 1, element 0")
        case List(0, _*) => println("First element 0, any other element")
        case List(x, y) => println(s"Match list: a list containing only two arbitrary elements,The element is: ${x},${y}")
    }

    //Equivalent to
    list2 match {
        case 1 :: _ :: _ ::Nil => println("The length is 3 and the first element is 1")
        case 0 :: Nil => println("Length 1, element 0")
        case 0 :: _ => println("First element 0, any other element")
        case x :: y :: Nil => println(s"Match list: a list containing only two arbitrary elements,The element is: ${x},${y}")
    }

}

Matching tuple example

def main(args: Array[String]): Unit = {

    //Define three tuples
    val a = (1, 2, 3)
    val b = (3, 4, 5)
    val c = (3, 4)

    a match {
        case (1, _, _) => println("The length is 3 and the first element is 1")
        case (_, _, 5) => println("The length is 3 and the tail element is 5")
        case _ => println("Mismatch")
    }

}

 

2.14 higher order function

Scala combines object-oriented and functional features. If a function's parameter list can receive function objects, then the function is called a high-order function.

2.14.1 function as value

Function objects can be passed to methods.

Example: convert each element in an integer list to the corresponding number of *.

def main(args: Array[String]): Unit = {
    val list = (1 to 5).toList
    val func = (x:Int) => "*" * x
    val list1 = list.map(func)
    println(list1)//List(*, **, ***, ****, *****)
}

2.14.2 anonymous functions

Functions that are not assigned to variables are anonymous functions

Example:

def main(args: Array[String]): Unit = {
  val list = (1 to 5).toList
  val list1 = list.map((x:Int) => "*" * x)
  val list2 = list.map("*" * _)
  println(list1)//List(*, **, ***, ****, *****)
  println(list2)//List(*, **, ***, ****, *****)
}

2.14.3 coritization

Corrilization refers to the process of converting a method that originally received multiple parameters into multiple methods with only one parameter list

Example: define a method to splice two strings

object ClassDemo {

  //Common writing
  def merge1(str1:String, str2:String): String = str1 + str2

  //Coriolis f1 representation function
  def merge2(str1:String, str2:String)(f1:(String, String) => String): String = f1(str1, str2)

  def main(args: Array[String]): Unit = {
    println(merge1("abc", "def"))//abcdef
    println(merge2("abc", "def")(_ + _))//abcdef
  }

}

2.14.4 closure

A closure is a function that can access data that is not in the current scope. (coritization is a closure)

Example: get the sum of two integers through closure

def main(args: Array[String]): Unit = {
    val x = 10
    val sum = (y:Int) => x + y
    println(sum(10))//20
}

2.14.5 control abstraction

Assuming that the parameter list of function A needs to receive A function B, and function B has neither input value nor return value, then function A is called control abstract function.

Example:

object ClassDemo {

  val func = (f1:() => Unit) => {
    println("welcome")
    f1()
    println("bye")
  }

  def main(args: Array[String]): Unit = {
    func(() => println("shopping.."))
  }

}

2.15 generics

2.15.1 generics

Generic refers to a specific data type. In Scala, generic is represented by [data type].

generic method

Example, define a generic method to obtain intermediate elements of any data type

def getMiddleElement[T](array: Array[T]): T = {array(array.length / 2)}

Generic class

For example, a Pair generic class is defined, which contains two fields and the field type is not fixed

class Pair[T](var a:T, var b:T)

Generic trait

trait Logger[T]{
  val a:T
  def show(b:T)
}

object ConsoleLogger extends Logger[String]{
  override val a: String = "sjh"
  override def show(b: String): Unit = println(b)
}

2.15.2 upper and lower bounds

upper bound

Use T <: type name to add an upper bound to the type, indicating that the type must be t or a subclass of T.

object ClassDemo {

  class Person
  class Student extends Person

  def demo[T <: Person](array: Array[T]): Unit = println(array)

  def main(args: Array[String]): Unit = {
    demo(Array(new Person))
    demo(Array(new Student))
    demo(Array("a"))//report errors
  }

}

Lower bound

Use t >: type name means to add a lower bound to the type, indicating that the type must be a parent of T or t.

If a generic has both an upper bound and a lower bound, the lower bound is written in front, [t >: a <: b]

2.15.3 covariant, inverter and non transformer

Covariance: there is a parent-child relationship between Class A and class B, and there is also a parent-child relationship between Pair[A] and Pari[B].

class Pair[+T]{}

Inversion: Class A and class B have a parent-child relationship, but Pair[A] and Pari[B] have a child parent relationship.

class Pair[-T]{}

Non variable: Class A and class B are parent-child relationships, and there is no relationship between Pair[A] and Pari[B].

class Pair[T]{} //The default type is immutable

Example:

object ClassDemo {

  class Super
  class Sub extends Super
  class Temp1[T]
  class Temp2[+T]
  class Temp3[-T]

  def main(args: Array[String]): Unit = {

    //Test non variable
    val t1:Temp1[Sub] = new Temp1[Sub]
    //val t2:Temp1[Super] = t1 error

    //Test covariance
    val t3:Temp2[Sub] = new Temp2[Sub]
    val t4:Temp2[Super] = t3

    //Test inverter
    val t5:Temp3[Super] = new Temp3[Super]
    val t6:Temp3[Sub] = t5
  }

}

2.16 assembly

Classification:

Mutable collection thread unsafe

The set itself can change dynamically, and the variable set provides methods to change the elements in the set.

scala.collection.mutable / / manual package import is required

Immutable collection thread safety

The default class library. Once the initialization of the elements in the collection is completed, they cannot be changed. Any change to the collection will generate a new collection.

scala.collection.immutable / / manual package import is not required

Set is unordered and unique

        ·HashSet

        ·SortedSet

                ·TreeSet

                ·BitSet

        ·ListSet

Seq sequence, ordered, repeatable, element indexed

High efficiency index sequence

· enhancement of numericrange

· Range ordered integer sequence, similar to arithmetic sequence

· Vector general immutable data structure, which takes a long time to obtain elements and updates randomly faster than arrays or lists

· String string

· LinearSeq linear sequence, which mainly operates the first and last elements

· List

· Queue queue

· Stack stack immutable Stack has been deprecated

· Stream

Map

        ·HashMap

        ·SortedMap

                ·TreeMap

        ·ListMap

Variable sets are richer than immutable sets. For example, in Seq, Buffer sets are added, such as ArrayBuffer and ListBuffer.

 

2.16.1 Traverable

Traverable is a trait whose sub trait is immutable Traverable and mutable Traverable is the parent trait of immutable set and variable set respectively.

Format:

Create an empty traversable object.

val t = Traverable.empty[Int]
val t = Traverable[Int]()
val t = Nil

Create a traversable object with parameters.

val t = List(1, 2, 3).toTraverable
val t = Traverable(1, 2, 3)//Generate List by default

 

Transpose:

Use the transfer method.

The transpose operation requires the same number of elements in each set.

def main(args: Array[String]): Unit = {
  val t1 = Traversable(Traversable(1, 4, 7), Traversable(2, 5, 8), Traversable(3, 6, 9))
  println(t1)//List(List(1, 4, 7), List(2, 5, 8), List(3, 6, 9))
  val transpose = t1.transpose
  println(transpose)//List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9))
}

 

Splicing:

++Data can be spliced, but a large number of temporary collections will be created, which can be realized through concat method.

def main(args: Array[String]): Unit = {
  val t1 = Traversable(1, 2, 3)
  val t2 = Traversable(4, 5, 6)
  val traversable = Traversable.concat(t1, t2)
  println(traversable)//List(1, 2, 3, 4, 5, 6)
}

 

Filter:

Use the collect method to realize the partial function, which is used in combination with the set to filter the specified data from the set.

def main(args: Array[String]): Unit = {

  val t1 = (1 to 10).toList
  def filter:PartialFunction[Int, Int] = {
    case x if x % 2 == 0 => x
  }

  //val t2 = t1.collect(filter)
  val t2 = t1.collect({
    case x if x % 2 == 0 => x
  })

  println(t2)//List(2, 4, 6, 8, 10)

}

 

scan method

def scan[B](z:B)(op: (B, B) => B)

[B] Represents the data type of the return value, (z:B) represents the initialization value, (OP: (B, b) = > b) represents the specific function operation.

Example: define a traversable set, store 1-5, assume the initial value is 1, and obtain the factorial value of each element respectively.

def main(args: Array[String]): Unit = {
  val t1 = 1 to 5
  //val seq = t1.scan(1)((a, b) => a * b)
  val seq = t1.scan(1)(_ * _)
  println(seq)//Vector(1, 1, 2, 6, 24, 120)
}

 

Gets the specified element of the collection

head/last: get the first / last element without throwing an exception

headOption/lastOption: get the first / last element, and the return value is Option

Find: find the first element of the symbol condition

slice: intercept some elements in the collection, close left and open right

def main(args: Array[String]): Unit = {
  val t1 = 1 to 5
  println(t1.head)//1
  println(t1.last)//5
  println(t1.headOption)//Some(1)
  println(t1.lastOption)//Some(5)
  println(t1.find(_ % 2 == 0))//Some(2)
  println(t1.slice(0, 2))//Vector(1, 2)
}

 

Judge whether the element is legal

forall returns true if all elements in the collection meet the conditions

exist returns true if an element in the collection meets the condition

def main(args: Array[String]): Unit = {
  val t1 = 1 to 5
  println(t1.forall(_ % 2 == 0))//false
  println(t1.exists(_ % 2 == 0))//true
}

 

Aggregate function

count counts the number of qualified elements in the collection

sum get collection elements and

product gets the scores of all elements in the collection

max gets the maximum value of all elements in the collection

min gets the minimum value of all elements in the set

 

Collection type conversion

toList

toSet

toArray

toSeq

 

Fill element

fill quickly generates a specified number of elements

The iterator generates a specified number of elements according to the specified conditions

range generates all the data of the specified interval in a certain interval. The interval parameter is 1 by default

def main(args: Array[String]): Unit = {

  val t1 = Traversable.fill(5)("a")
  println(t1)//List(a, a, a, a, a)

  val t2 = Traversable.fill(2, 2, 2)("a")
  println(t2)//List(List(List(a, a), List(a, a)), List(List(a, a), List(a, a)))

  val t3 = Traversable.iterate(1, 5)(_ * 10)
  println(t3)//List(1, 10, 100, 1000, 10000)

  val t4 = Traversable.range(1, 100, 7)
  println(t4)//List(1, 8, 15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99)

}

 

Iterable

Iteratable represents a set that can be iterated. It inherits the Travsersable trait and is also the parent trait of other sets. It defines the method of obtaining iterators, which is an abstract method.

Example of traversing a collection:

def main(args: Array[String]): Unit = {

  val list = List(1, 2, 3, 4, 5)

  //Mode 1: active iteration
  val iterator = list.iterator
  while (iterator.hasNext)
    print(iterator.next() + " ")

  //Mode 2 passive iteration
  list.foreach(x => print(x + " "))

}

 

Group traversal example:

def main(args: Array[String]): Unit = {
  val i = (1 to 5).toIterable
  val iterator = i.grouped(2)
  while (iterator.hasNext)
    print(iterator.next() +" ")//Vector(1, 2) Vector(3, 4) Vector(5)
}

 

Generate tuples by index:

def main(args: Array[String]): Unit = {
    val i = Iterable("A", "B", "C", "D", "E")
    val tuples = i.zipWithIndex.map(x => x._2 -> x._1)
    println(tuples)//List((0,A), (1,B), (2,C), (3,D), (4,E))
}

 

Judge whether the set is the same:

def main(args: Array[String]): Unit = {

  val i1 = Iterable("A", "B", "C")
  val i2 = Iterable("A", "C", "B")
  val i3 = Iterable("A", "B", "C")

  println(i1.sameElements(i2))//false
  println(i1.sameElements(i3))//true

}

 

2.16.2 Seq

Seq trait represents the sequence of elements arranged in a certain order. Sequence is a special iterative set, which is characterized by order, repeatability and index

 

To create a Seq set:

def main(args: Array[String]): Unit = {
  val seq = (1 to 5).toSeq
  println(seq)//Range(1, 2, 3, 4, 5)
}

 

Get length and element:

Get the length through the length or size method, and get the element directly through the index.

def main(args: Array[String]): Unit = {
  val seq = (1 to 5).toSeq
  println(seq.length)//5
  println(seq.size)//5
  println(seq(0))//1
}

 

Gets the index value of the specified element

indexOf gets the first occurrence position of the specified element in the list

lastIndexOf gets the position of the last occurrence of the specified element in the list

indexWhere gets the element that meets the condition and the index that appears for the first time in the collection

lastIndexWhere gets the element that meets the condition and the index of the last occurrence in the collection

indexOfSlice gets the first occurrence position of the specified subsequence in the collection

Cannot find return - 1.

 

Determine whether the specified data is included:

Does startsWith begin with a reference to the stator sequence

Whether endsWith ends with a reference sequence

contains determines whether a specified data is included

containsSlice determines whether a specified subsequence is included

 

Modify the specified element:

updated modifies the element of the specified index position to the specified value.

patch modifies the element of the specified interval to the specified value.

def main(args: Array[String]): Unit = {
  val seq = (1 to 5).toSeq
  val seq1 = seq.updated(0, 5)
  println(seq1)//Vector(5, 2, 3, 4, 5)
  //Parameter 1 initial index parameter 2 replaced element parameter 3 replaced several
  val seq2 = seq.patch(1, Seq(1, 2), 3)
  println(seq2)//Vector(1, 1, 2, 4, 5)
}

 

2.16.3 Stack

Top get stack top element

push stack

pop out of stack

Clear clear all elements

mutable.Stack has a unique method pushAll, which pushes multiple elements into the stack.

ArrayStack has a unique method: dup, copy the top element of the stack. preseving, execute the expression, and restore the stack after execution.

Example:

def main(args: Array[String]): Unit = {

  //Stack from right to left
  val s = mutable.Stack(1, 2, 3, 4, 5)

  println(s.top)//1
  println(s.push(6))//Stack(6, 1, 2, 3, 4, 5)
  println(s.pushAll(Seq(7, 8, 9)))//Stack(9, 8, 7, 6, 1, 2, 3, 4, 5)
  println(s.pop())//9
  println(s.clear())//()

}

Example: define variable stack storage 1-5, copy the top elements of the stack through dup method, and empty the elements first and then restore through preseving method.

def main(args: Array[String]): Unit = {

  //Stack from right to left
  val s = mutable.ArrayStack(1, 2, 3, 4, 5)

  //Copy stack top element
  s.dup()

  println(s)//ArrayStack(1, 1, 2, 3, 4, 5)

  s.preserving({
    //After this method is executed, the data in the stack will be recovered
    s.clear()
  })

  println(s)//ArrayStack(1, 1, 2, 3, 4, 5)

}

 

2.16.4 Queue

Represents a queue, which is characterized by FIFO. The commonly used queue is mutable Queue, which is internally implemented by MutableList.

enqueue join

dequeue out

dequeueAll removes all elements that meet the criteria

dequeueFirst removes the first element that satisfies the condition

 

3. Actor model

Introduction to Actor

The Actor concurrent programming model in Scala can be used to develop concurrent programs that are more efficient than Java threads.

Problems of Java Concurrent Programming

In Java Concurrent Programming, each object has a logic monitor, which can be used to control the multi-threaded access of the object. We add the synchronized keyword to mark that synchronous lock access is required. The locking mechanism ensures that only one thread accesses the shared data at the same time. However, there are resource competition and deadlock problems in this way. The larger the program, the more troublesome the problem is.

Resource competition

 

thread deadlock

 

Actor concurrent programming model

The concurrent programming model provided by Scala is not the same as the concurrent programming model provided by Scala. Actor concurrent programming model is a concurrent programming mode that does not share data and relies on message transmission, which can effectively avoid resource contention, deadlock and so on.

 

Topics: Scala