Chapter 1 Introduction to Scala
1.1 general
Scala is a static type programming language that takes Java virtual machine (JVM) as the running environment and combines the best features of object-oriented and functional programming (static languages need to be compiled in advance, such as Java, c, c + +, dynamic languages such as js).
1) Scala is a multi paradigm programming language. Scala supports object-oriented and functional programming. (multi paradigm is a variety of programming methods
The meaning of law. There are four programming methods: process oriented, object-oriented, generic and functional.)
2) scala source code (. scala) will be compiled into Java bytecode (. Class), and then run on the JVM. You can call the existing Java class library to realize the seamless connection between the two languages.
3) As a single language, Scala is very concise and efficient.
4) In the design of Scala, Martin odesky refers to the design idea of Java. It can be said that Scala originates from Java. At the same time, Martin odesky also adds his own idea to integrate the characteristics of functional programming language into Java. Therefore, for students who have studied Java, they should only find out the similarities and differences between Scala and Java in the process of learning Scala, You can quickly master the language Scala.
1.2 environment construction
Based on jdk1 eight
Download scala2 twelve point one one
Configuring scala environment variables
1.3 coding
package chapter01 class Student(name:String,info: Int) { def printInfo():Unit ={ println(name+" "+info+" "+Student.school) } } object Student{ val school:String = "Hebei Agricultural University" //Companion Object def main(args: Array[String]): Unit = { val student = new Student("Zhang San",20) student.printInfo() } }
Student$.class
package chapter01; public final class Student$ { public static MODULE$; private final String school; static { new (); } public String school() { return this.school; } public void main(String[] args) { Student student = new Student("Zhang San", 20); student.printInfo(); } private Student$() { MODULE$ = this; this.school = "Hebei Agricultural University"; } }
Student.java
package chapter01; import scala.Predef.; import scala.reflect.ScalaSignature; @ScalaSignature(bytes="\006\001}2Aa\003\007\001\037!Aa\003\001B\001B\003%q\003\003\005#\001\t\005\t\025!\003$\021\0251\003\001\"\001(\021\025a\003\001\"\001.\017\025\tD\002#\0013\r\025YA\002#\0014\021\0251c\001\"\0015\021\035)dA1A\005\002YBaa\016\004!\002\0239\002\"\002\035\007\t\003I$aB*uk\022,g\016\036\006\002\033\005I1\r[1qi\026\024\b'M\002\001'\t\001\001\003\005\002\022)5\t!CC\001\024\003\025\0318-\0317b\023\t)\"C\001\004B]f\024VMZ\001\005]\006lW\r\005\002\031?9\021\021$\b\t\0035Ii\021a\007\006\00399\ta\001\020:p_Rt\024B\001\020\023\003\031\001&/\0323fM&\021\001%\t\002\007'R\024\030N\\4\013\005y\021\022\001B5oM>\004\"!\005\023\n\005\025\022\"aA%oi\0061A(\0338jiz\"2\001\013\026,!\tI\003!D\001\r\021\02512\0011\001\030\021\025\0213\0011\001$\003%\001(/\0338u\023:4w\016F\001/!\t\tr&\003\0021%\t!QK\\5u\003\035\031F/\0363f]R\004\"!\013\004\024\005\031\001B#\001\032\002\rM\034\007n\\8m+\0059\022aB:dQ>|G\016I\001\005[\006Lg\016\006\002/u!)1H\003a\001y\005!\021M]4t!\r\tRhF\005\003}I\021Q!\021:sCf\004") public class Student { private final String name; private final int info; public static void main(String[] paramArrayOfString) { Student..MODULE$.main(paramArrayOfString); } public static String school() { return Student..MODULE$.school(); } public void printInfo() { Predef..MODULE$.println(2 + this.name + " " + this.info + " " + Student..MODULE$.school()); } public Student(String name, int info) { } }
Chapter II variables and data types
2.1 variables and constants
var variable name: variable type = value
val constant name: constant type = value
Variable types can be omitted, and the compiler will automatically infer
Variables are not needed where constants can be used
(1) When declaring variables, types can be omitted
(2) It cannot be modified after the type is determined
(3) When a variable is declared, it must have an initial value
(4) When declaring variables, you can use var and Val, var can be changed and val cannot be changed
2.2 specification of identifiers
Starts with an operator and contains only operators (+ - * / #! Etc.)
Use back quotation marks Any string included, even Scala keywords (39) can be used
• package, import, class, object, trait, extends, with, type, for • private, protected, abstract, sealed, final, implicit, lazy, override
• try, catch, finally, throw
• if, else, match, case, do, while, for, return, yield
• def, val, var
• this, super • new • true, false, null
2.3 string
(1) String, connected by + sign, can be multiplied by string
(2) printf usage: string, passing value through%.
(3) String template (interpolation string): get variable value through $
var age="hello" println(s"${age}") var num = 2.3456 println(f"The num is ${num}%.2f")//Keep two decimal places println(raw"The num is ${num}%.2f")//raw output original format //The three quotation mark format can wrap multiple lines of text and keep the original format s"""""".stripMargin
2.4 keyboard input
StdIn is the new Scanner
Basic grammar
StdIn.readLine(),StdIn.readShort(),StdIn.readDouble()
2.5 document operation
def main(args: Array[String]): Unit = { //read file Source.fromFile("src/main/resources/test.txt").foreach(print) //Write data to a file. scala does not have a well encapsulated class library for writing to a file. Just use Java io val writer = new PrintWriter(new File("src/main/resources/test1.txt")) writer.write("hello scala from java writer") writer.close() }
2.6 data type
1) All data in Scala are objects and subclasses of Any.
2) In Scala, data types are divided into two categories: numeric type (AnyVal) and reference type (AnyRef). Both value type and reference type are objects.
3) Scala data types still comply with the principle of automatic conversion (implicit conversion) from low-precision value types to high-precision value types
4) StringOps in Scala is an enhancement of String in Java
5) Unit: corresponds to void in Java. It is used for the position of the return value of the method, indicating that the method has no return value. Unit is a data type, and only one object is (). Void is not a data type, but a keyword
6) Null is a type, and only one object is null. It is a subclass of all reference types (AnyRef).
Nothing is a subclass of all data types. It is mainly used when a function has no explicit return value, because in this way, we can return the thrown return value to any variable or function
Chapter III process control
3.1 if else
Syntax is no different from java
But each branch can return a value
The type returned is the last line of branch code block
val age = StdIn.readInt() var result = if (age>18){ println("18") 15 } else{ "000" } println(result)
3.2 for
to unitl
The difference is that until has no right boundary
for(i <- 1 to 3){ print(i + " ") } println() ------------------------------------------------------ for(i <- 1.to(3){ print(i + " ") }
The bottom layer is the method called
for (i <- Range(1,10)){} //Range without boundary is the companion object for (i <- 1 until 10){} //The bottom is the top
foreach loop in scala
for (i <- Array(10,20,30)) for (i <- List(10,20,30)) for (i <- Set(10,20,30))
Cycle guard
There is no continue in scala
for (i <- 0 to 10 if i!=5){}
Cycle step
for(i <- 1 to 3 by 2){} //Step cannot be 0
reverse
for(i <- 1 to 3 reverse){} for(i <- 3 to 1 by -1){}
loop nesting
for(i <- 1 to 3; j <- 1 to 3) { println(" i =" + i + " j = " + j) } //equivalence for (i <- 1 to 3) { for (j <- 1 to 3) { println("i =" + i + " j=" + j) } }
Loop return value
Rarely used
object TestFor { def main(args: Array[String]): Unit = { var res = for(i <-1 to 10) yield { i * 2 } println(res) } } Output result: Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
3.3 while do
Because there is no return value in while, when the statement is used to calculate and return the result, it is inevitable to use variables. If the variables need to be declared outside the while loop, it is equivalent to the internal of the loop, which has an impact on the external variables. Therefore, it is not recommended to use, but to use the for loop.
Same as java syntax
3.4 cycle interruption
Scala's built-in control structure specifically removes break and continue in order to better adapt to functional programming. It is recommended to use functional style to solve the functions of break and continue, rather than a keyword. Scala uses breakable control structure to realize break and continue functions.
import scala.util.control.Breaks import scala.util.control.Breaks._ def main(args: Array[String]): Unit = { Breaks.breakable( for (elem <- 1 to 10) { println(elem) if (elem == 5) Breaks.break()//break() } ) println("Normal end of cycle") }
Chapter 4 functional programming
4.1 differences between functions and methods
1) Core concept
(1) A collection of program statements that complete a function is called a function.
(2) Functions in a class are called methods.
2) Case practice
(1) The Scala language can declare any syntax in any syntax structure
(2) Function has no concept of overloading and rewriting; Methods can be overloaded and overridden
(3) Functions in Scala can be defined nested
4.2 function parameters
(1) Variable parameters
(2) If there are multiple parameters in the parameter list, the variable parameters are generally placed last
(3) Parameter default value: generally, the parameter with default value is placed behind the parameter list
(4) Named parameter
Mutable is similar to python
def hello (*str): print(type(str)) hello("sac","1") ------------------------ <class 'tuple'>
def hello(string: String*)={ println(string) } println(hello("1","2")) ---------------------------- WrappedArray(1, 2)
Default value
def hello(string: String = "hello")={ println(string) }
Named parameter
def hello(name,age)={ println(name+age) } hello(age=15,name="Zhang San")
4.3 principle of simplifying functions (key points)
Function saving principle
(1) Return can be omitted. Scala will use the last line of the function body as the return value
(2) If the function body has only one line of code, you can omit curly braces
(3) If the return value type can be inferred, it can be omitted (: omitted together with the return value type)
(4) If there is a return, the return value type cannot be omitted and must be specified
(5) If the function explicitly declares unit, even if the return keyword is used in the function body, it will not work
(6) Scala can omit the equal sign if it expects a type with no return value
(7) If the function has no parameters but declares a parameter list, parentheses can be added or not when calling
(8) If the function does not have a parameter list, the parentheses can be omitted and must be omitted when calling
(9) If you don't care about the name and only care about logical processing, the function name (def) can be omitted
Anonymous function lambda expression
4.4 anonymous functions
A function without a name is an anonymous function.
(X: int) = > {function body}
def fun1(name:String): Unit ={ println(name) } val tmp = (name:String)=>{println(name)} def fun2(fun:String => Unit): Unit ={ fun("Zhang San") } fun2(tmp)
(1) The type of parameter can be omitted and will be automatically deduced according to the formal parameter
fun2((name)=>{println(name)})
(2) If only one parameter is found after the type is omitted, the parentheses can be omitted; Other situations: if there are no parameters and the parameters exceed 1, the parentheses can never be omitted.
fun2( name =>{println(name)})
(3) If an anonymous function has only one line, braces can also be omitted
fun2( name => println(name))
(4) If the parameter appears only once, the parameter is omitted and the following parameters can be used_ replace
x fun2( name => println(_)) fun2( println(_))
Outrageous Edition
fun2(println)
4.5 advanced functions
Function object
def fun1(name:String): Unit ={ println(name) } val tmp = (name:String)=>{println(name)} def fun2(fun:String => Unit): Unit ={ fun("Zhang San") } val f1 = fun2 _ val f2: String => Unit= fun1
val f1 = fun2 _
You can also return a function object
Function assignment
def func1(s:String): Char=>(Int=>Boolean)={ def func2(c:Char): Int=>Boolean ={ def fun3(i:Int):Boolean ={ if(i==0&&c=='0'&&s=='0') true else false } fun3 } func2 }
Function coritization
def func1(i:Int)(s:String)(c:Char):Boolean={ true }
4.6 closure
Closure: standard configuration of functional programming
Closure: if a function accesses the value of its external (local) variable, the function and its environment are called closures
def func1(s:String): Char=>(Int=>Boolean)={ def func2(c:Char): Int=>Boolean ={ def fun3(i:Int):Boolean ={ if(i==0&&c=='0'&&s=='0') true else false } fun3 } func2 }
When func1 is called, the local variables of the pop-up stack will also be released, but fun3 can still access the local variables of the upper function
This is because scala packages the function objects created by local variables and puts them in heap memory,
4.7 recursion
def con(n:Int): Int = { if (n ==0) return 1 con(n-1) * n } //Tail recursion saves stack space, and the pointer does not need to change def con1(n:Int):Int = { @tailrec //This annotation checks whether the tail recursion is correct def loo(n:Int,sum:Int):Int = { if(n==0) return sum loo(n-1,sum * n) } loo(n,1) }
4.8 control abstraction
1) Value call: pass the calculated value
object TestControl { def main(args: Array[String]): Unit = { def f = ()=>{ println("f...") 10 } foo(f()) } def foo(a: Int):Unit = { println(a) println(a) } }
2) Call Name: pass the code
object TestControl { def main(args: Array[String]): Unit = { def f = ()=>{ println("f...") 10 } foo(f()) } //def foo(a: Int):Unit = { def foo(a: =>Int):Unit = {//Notice that there are no parentheses for variable a println(a) println(a) } } Output result: f... 10 f... 10
Define your own while loop
def myWhile(flag: => Boolean): (=> Unit)=>Unit= { def dowhile(con: => Unit):Unit = { con if (flag) dowhile(con) } dowhile } var n=10 myWhile(n>=1){ println(n) n-=1 } }
4.9 lazy loading
When the return value of the function is declared as lazy, the execution of the function will be delayed until we take this value for the first time. This kind of function is called inert function.
Chapter V object oriented
5.1 package description (package statement)
Scala has two package management styles. One is the same as the package management style of Java. Each source file has a package (the package name and the path of the source file are not required to be consistent), and the package name uses "." Separate to represent the hierarchical relationship of packages, such as com atguigu. scala. The other style represents the hierarchical relationship through nested styles, as follows
package com{ package atguigu{ package scala{ } } }
The second style has the following characteristics:
(1) Multiple package s can be declared in one source file
(2) The classes in the child package can directly access the contents in the parent package without importing the package
5.2 package object
In Scala, you can define a package object with the same name for each package. The members defined in the package object can be accessed directly as the shared variables of all class es and objects under its corresponding package.
package object com{ val shareValue="share" def shareMethod()={} }
If the package is managed in a nested way, the package object can be defined in the same file as the package, but the package object and package declaration should be guaranteed to be in the same scope.
5.3 guide package description
1) Like Java, import can be used at the top, and all classes in this file can be used.
2) Partial import: when to use and when to import. It can be used within its scope of action
3) Wildcard import: import Java util._
4) Name the class: import Java util. {ArrayList=>JL}
5) Import multiple classes of the same package: import Java util. {HashSet, ArrayList}
6) Shielding class: import Java util. {ArrayList =>,}
7) Absolute path of imported package: new root java. util. HashMap
The three default imports in Scala are
import java.lang._
import scala._
import scala.Predef._
5.4 classes and objects
Define class
[modifier] class{
}Public is assumed by default without modifier, and an error will be reported if public is added
A scala file can define multiple classes
class student{ //This annotation generates set get by default @BeanProperty private var:String name = "1" //The default is public, but the bottom layer is private //If you want the attribute to be empty, name =_ Equivalent to null or 0 }
5.5 packaging
The public attribute in scala is actually private at the bottom, and it is operated through the get method (obj.field()) and the set method (obj. Field = (value)). Therefore, Scala does not recommend setting the property to private and then setting the public get and set methods for it. However, since many Java frameworks use reflection to call getXXX and setXXX methods, sometimes in order to be compatible with these frameworks, getXXX and setXXX methods will also be set for Scala properties (implemented through @ BeanProperty annotation).
In Java, access permissions are divided into public, private, protected and default. In Scala, you can achieve the same effect with similar modifiers. But there are differences in use.
(1) The default access permission of properties and methods in Scala is public, but there is no public keyword in Scala.
(2) Private is a private permission, which is only available in the interior of a class and its associated objects.
(3) Protected refers to the protected permission. The protected permission in Scala is more strict than that in Java. The same kind and subclass can be accessed, but the same package cannot be accessed.
(4) private [package name] adds package access permission. Other classes under the package name can also be used
5.6 constructor
Like Java, Scala construction objects also need to call construction methods, and there can be any number of construction methods.
The constructors of Scala class include: main constructor and auxiliary constructor
class Class name(parameter list ) { // primary constructor // Class body def this(parameter list ) { // Auxiliary constructor } def this(parameter list ) { //Auxiliary constructors can have multiple } }
explain:
(1) Auxiliary constructor, the name of the function this, can be multiple. The compiler can distinguish it by the number and type of parameters.
(2) Auxiliary construction methods cannot directly build objects. They must call the main construction method directly or indirectly.
(3) The constructor calls other constructors, which requires that the called constructor must be declared in advance.
5.7 abstract classes
(1) Define abstract class: abstract class Person {} / / mark the abstract class with the abstract keyword
(2) Define abstract attribute: val|var name:String / / an attribute is an abstract attribute without initialization
(3) Define abstract methods: def hello():String / / methods that are declared but not implemented are abstract methods
Rewrite & inherit
(1) If the parent class is an abstract class, the subclass needs to implement the abstract properties and methods, otherwise the subclass also needs to be declared as an abstract class
(2) Overriding non abstract methods requires overriding. Overriding abstract methods can be done without overriding.
(3) the method of calling the parent class in the subclass uses the super keyword.
(4) The subclass implements the abstract attribute, and the abstract attribute of the parent class can be modified with var;
The subclass overrides the non Abstract attribute. The non Abstract attribute of the parent class only supports val type, not var.
Because var is modified as a variable, it can be used directly after subclass inheritance, and there is no need to rewrite it
5.8 single case object (companion object)
1) Basic syntax object person {Val country: String = "China"}
2) Explain
(1) The singleton object is declared with the object keyword
(2) The class corresponding to a singleton object is called an associated class, and the name of the associated object should be consistent with the name of the associated class.
(3) The properties and methods in the singleton object can be accessed directly through the associated object name (class name).
apply method
Through the apply method of the associated object, the object is created without using the new method.
If you want to make the main constructor private, you can add private before ().
When you use the new keyword to build an object, you actually call the construction method of the class. When you directly use the class name to build an object, you call the apply method of the real-time associated object.
5.9 Trait
It is implemented by the interface in java
Basic grammar
trait Trait name { subject }
Traits in Scala can have either abstract attributes and methods or concrete attributes and methods
When the trait conflicts with the class attribute, the attribute needs to be rewritten, otherwise an error will be reported
scala is bound dynamically
No parent class: class name extends trait 1 with trait 2 with trait 3
Parent class: class name extends parent class with trait 1 with trait 2 with trait 3
Multiple trait method conflicts
trait Ball { def describe(): String = { "ball" } } trait Color extends Ball { override def describe(): String = { "blue-" + super.describe() } } trait Category extends Ball { override def describe(): String = { "foot-" + super.describe() } } class MyBall extends Category with Color { override def describe(): String = { "my ball is a " + super.describe() } } object TestTrait { def main(args: Array[String]): Unit = { println(new MyBall().describe()) } } //Output results //my ball isa blue-foot-ball
5.9 type check and conversion
(1)obj.isInstanceOf[T]: judge whether obj is of type T.
(2)obj.asInstanceOf[T]: strong conversion of obj to T type.
(3) classOf gets the class name of the object.
class Person{ } object Person { def main(args: Array[String]): Unit = { val person = new Person //(1) Determine whether the object is an instance of a type val bool: Boolean = person.isInstanceOf[Person] if ( bool ) { //(2) Converts an object to an instance of a type val p1: Person = person.asInstanceOf[Person] println(p1) } //(3) Get class information val pClass: Class[Person] = classOf[Person] println(pClass) } }
5.10 enumeration class and application class
Enumeration class: it needs to inherit enumeration
Application class: need to inherit App
// Enumeration class object Color extends Enumeration { val RED = Value(1, "red") val YELLOW = Value(2, "yellow") val BLUE = Value(3, "blue") } // Application class object Test20 extends App { println("xxxxxxxxxxx"); }
Use the type keyword to define a new data type name, which is essentially an alias of the type
type myString = String
Chapter VI collection
6.1 variable and immutable
Scala's collections fall into three categories: sequence Seq, Set and Map. All collections are extended from Iterable.
For almost all collection classes, Scala provides both variable and immutable versions, which are located in the following two packages
Immutable set: Scala collection. immutable
Variable set: Scala collection. mutable
Scala immutable set means that the set object cannot be modified. Each modification will return a new object without modifying the original object. Similar to String objects in java
A variable set is a set that can directly modify the original object without returning a new object. Similar to the StringBuilder object in java
Array and String are special, and implicit conversion is used
Set and Map are collections in Java, but Seq is not in Java. We found that List belongs to Seq, but it is different from List
The for loop has a 1 to 3, which is the Range under IndexedSeq, and the String also belongs to IndexedSeq
Classical data structures such as Queue and Stack are assigned to linear SEQ (linear sequence)
The Map system in scala has a SortedMap, which shows that Scala's Map can support sorting
The difference between IndexedSeq and LinearSeq:
IndexedSeq searches and locates by index, so it is fast. For example, String is an index set
LinearSeq is linear, that is, it has the concept of head and tail. This data structure is generally searched through history
6.2 traversal
definition
definition: val arr1 = new Array[Int](10) println(arr01.length) // 4 //(2) Array assignment //(2.1) modify the value of an element arr01(3) = 10 //(2.2) assign value to the array in the form of method arr01.update(0,1) //(3) Traversal array //(3.1) view array println(arr01.mkString(",")) //(3.2) general traversal for (i <- arr01) { println(i) } //(3.3) simplified traversal def printx(elem:Int): Unit = { println(elem) } arr01.foreach(printx) // arr01.foreach((x)=>{println(x)}) // arr01.foreach(println(_)) arr01.foreach(println) //(4) Adding elements (because you create an immutable array, adding elements actually generates new numbers Group) println(arr01) val ints: Array[Int] = arr01 :+ 5 println(ints) }
The second way is to define an array
val arr1 = Array(1, 2)
(1) When defining an array, initial values are assigned directly
(2) Use the apply method to create an array object
6.3 array
val arr01 = ArrayBuffer[Any](3, 2, 5) arr01.+=(4) //(3.2) add data to the last array arr01.append(5,6) //Inserts data into the specified location (0) arr01.insert(0,7,8) arr01.preappend(5,6) //Deletes the specified subscript element arr.remove(0) //Delete multiple from subscript arr.remove(1,3) arr1.toBuffer //Immutable array to variable array arr2.toArray //Variable array to immutable array //Remove 1 element from array arr -= 1 //Specify delimiter traversal arr.mkString(", ") //Returns the range of length a.indices
ArrayBuffer is an ordered collection. The append method () is used to add elements, and variable parameters are supported
Multidimensional array
val arr = Array.ofDim[Double](3,4) //Description: there are three one-dimensional arrays in the two-dimensional array, and each one-dimensional array has four elements
6.4 list
There is a sequence that cannot be created with a constructor. The bottom layer inherits an abstract class
Only use apply
The value cannot be changed and can be added
//apply method creation var list = List(0,1) var list1 = Nil.::(1) var list2 = 1 :: 2 :: 3 :: Nil //The two classes implement List Nil. The empty list class:: Class:: method adds the element to the end and returns a new list //List append list:: returns a nested list that is not the desired append element // : this method will synthesize a complete list or++ // ++A new + + = will be returned and the first one will be overwritten
Variable list
ListBuffer
new and apply
new ListBuffer[Int]() //Length cannot be defined in advance ListBuffer(1,2) 3 +=: 4 list += 25 += 25
6.4 assembly
Variable set and immutable set have the same name, but the package name is different
set is a trait. It uses the apply method of the associated object and is out of order
The method is consistent with the list
val list1: List[Int] = List(1, 2, 3, 4, 5, 6, 7) val list2: List[Int] = List(4, 5, 6, 7, 8, 9, 10) //(1) Gets the header of the collection println(list1.head) //(2) Get the tail of the collection (either the head or the tail) println(list1.tail) //(3) Set last data println(list1.last) //(4) Set initial data (excluding the last one) println(list1.init) //(5) Reverse println(list1.reverse) //(6) Take the first (last) n elements println(list1.take(3)) println(list1.takeRight(3)) //(7) Remove the first (last) n elements println(list1.drop(3)) println(list1.dropRight(3)) //(8) Union println(list1.union(list2)) //(9) Intersection println(list1.intersect(list2)) //(10) Difference set println(list1.diff(list2)) //(11) Zipper note: if the number of elements in two sets is not equal, the same amount of data will be zipped. If the nested Tuple2 type is not used, the redundant data will be omitted println(list1.zip(list2)) //(12) Sliding window list1.sliding(2, 5).foreach(println)
6.5 Map
Map("a" -> 1) var a :Map [String , String] = Map() map.get("a") //Will not return value, will return Some(1) want to return value get(). get //When there is no key value, get will report an exception. Use getOrElse("c",0) //If null, assign 0 //You can also use map("a") to report exceptions map.put("a","b") //Key pair deletion a map -= "a" println(map) map += "sczc" -> "s" map.update("scac","nu") map += (("1","1")) println(map) //Merge map map ++= mutable.Map ("2"-> "2") println(map)
6.6 tuples
//The tuple has a maximum of 22 elements. The creation method is the same as py (). The subscript is immutable from the beginning //Not a list of Any type. Each tuple length has a separate class Tuple1-22 var tuple = ("1",1,2.1,true) println(tuple) //(1,1,2.1,true) //Access data tuple_ number or tuple. produceElement(num) println(tuple._1) //Iterator traversal for (elem <- tuple.productIterator) println(elem) //Nested tuple var tuple2 = (1,2,(3,3)) println(tuple2._3._1)
Set common functions
//(1) Sum println(list.sum) //(2) Product println(list.product) //(3) Maximum println(list.max) //(4) Minimum value println(list.min) //(5) Sort // (5.1) sort by element size println(list.sortBy(x => x)) // (5.2) sort by absolute value of elements println(list.sortBy(x => x.abs)) // (5.3) sort by element size in ascending order println(list.sortWith((x, y) => x < y)) // (5.4) sort by element size in descending order println(list.sortWith((x, y) => x > y))
(1) sorted sorts a collection naturally by passing implicit Ordering
(2) sortBy sorts one or more attributes by their type.
(3) sortWith is based on the sorting of functions, and realizes the logic of user-defined sorting through a comparator function. lamda expression
Set computing advanced functions
val list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9) val nestedList: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9)) val wordList: List[String] = List("hello world","hello atguigu", "hello scala") //(1) Filter println(list.filter(x => x % 2 == 0)) //(2) Conversion / mapping println(list.map(x => x + 1)) //(3) Flattening println(nestedList.flatten) //(4) Flattening + mapping note: flatMap is equivalent to map operation first and then flatten operation println(wordList.flatMap(x => x.split(" "))) //(5) Grouping println(list.groupBy(x => x % 2)) }
Reduce method
Aggregate the data in the collection through the specified logic, so as to reduce the data and finally obtain the result.
val list = List(1,2,3,4) // Combine the data to realize the operation rules val i: Int = list.reduce( (x,y) => x-y ) println("i = " + i) // From the perspective of source code, the bottom layer of reduce actually calls reduceLeft //val i1 = list.reduceLeft((x,y) => x-y)
Fold folding: a special case of simplification.
val list = List(1,2,3,4) // The fold method uses function coritization, and there are two parameter lists // The first parameter list is: zero value (initial value) // The second parameter list is: simplification rules // The bottom layer of fold is actually foldLeft val i = list.foldLeft(1)((x,y)=>x-y) val i1 = list.foldRight(10)((x,y)=>x-y
Multithreading
(1 to 100).par.map() //Multiple x's
Chapter 7 pattern matching
Pattern matching in Scala is similar to the switch syntax in Java
var result = operator match { case '+' => a + b case '-' => a - b case '*' => a * b case '/' => a / b case _ => "illegal" }
In each case, there is no need to use the break statement to automatically interrupt the case.
Matching type
def describe(x: Any) = x match { case i: Int => "Int" case s: String => "String hello" case m: List[_] => "List" case c: Array[Int] => "Array[Int]" case someThing => "something else " + someThing }
Matching array
scala pattern matching can accurately match collections, such as an array with only two elements and the first element is 0.
val result = arr match { case Array(0) => "0" //Match Array(0) case Array(x, y) => x + "," + y //Matches the number of two elements Group, and then assign the element value to the corresponding x,y case Array(0, _*) => "Array starting with 0" //Match starts with 0 and array case _ => "something else" }
Match list
def main(args: Array[String]): Unit = { val list: List[Int] = List(1, 2, 5, 6, 7) list match { case first :: second :: rest => println(first + "-" + second + "-" + rest) case _ => println("something else") } }
Match on variable declaration
var first :: second :: three = List(121,2 ,3.5,6) println(s"$first $second") //for loop simplification for((var1,var2) <- List((1,2),(3,5))) println(var1+" "+var2) //You can replace the value var2 regardless of the position with_ Only the first value is traversed for((var1,_) <- List((1,2),(3,5))) println(var1) //The specified position special value only traverses tuples starting with 1 for((1,_) <- List((1,2),(3,5))) println(var1)
Matching objects and sample classes
object User{ def apply(name: String, age: Int): User = new User(name, age) def unapply(user: User): Option[(String, Int)] = { if (user == null) None else Some(user.name, user.age) } } object TestMatchUnapply { def main(args: Array[String]): Unit = { val user: User = User("zhangsan", 11) val result = user match { case User("zhangsan", 11) => "yes" case _ => "no" } println(result) } }
When User("zhangsan", 11) is written after case [case User("zhangsan", 11) = > "yes"], the unapply method (object extractor) will be called by default. User is used as the parameter of the unapply method. The unapply method extracts the name and age attributes of the user object and matches the attribute values in User("zhangsan", 11)
If the unapply method (extractor) of the object in case returns Some and all attributes are consistent, the matching is successful. If the attributes are inconsistent or return None, the matching fails.
Sample class
case class Person (name: String, age: Int)
○ 1 the sample class is still a class. Compared with ordinary classes, it only automatically generates associated objects, and some common methods are automatically provided in the associated objects, such as apply, unapply, toString, equals, hashCode and copy.
○ 2 the sample class is optimized for pattern matching, because it provides the unapply method by default. Therefore, the sample class can directly use pattern matching without implementing the unapply method by itself.
○ 3 every parameter in the constructor becomes val unless it is explicitly declared as var (this is not recommended)
Pattern matching in partial function (understanding)
The function is to return the second element of the input List set
Chapter 8 implicit transformation
exception handling
def main(args: Array[String]): Unit = { try { var n= 10 / 0 }catch { case ex: ArithmeticException=>{ // Arithmetic exception occurred println("Arithmetic exception occurred") } case ex: Exception=>{ // Exception handling println("Exception 1 occurred") println("Exception 2 occurred") } }finally { println("finally") } }
Use the throw keyword to throw an exception object. All exceptions are subtypes of Throwable. Throw expressions are typed, which is Nothing
When the compiler fails to compile for the first time, it will find the method that can make the code compile in the current environment, which is used to convert the type and realize secondary compilation
implicit function
class MyRichInt(val self: Int) { def myMax(i: Int): Int = { if (self < i) i else self } def myMin(i: Int): Int = { if (self < i) self else i } } object TestImplicitFunction { // Functions declared with the implicit keyword are called implicit functions implicit def convert(arg: Int): MyRichInt = { new MyRichInt(arg) } def main(args: Array[String]): Unit = { // When you want to call an object function, if the compilation is wrong, the compiler will try to be in the current scope Find the conversion rule that can call the corresponding function within the scope. This calling process is completed by the compiler, so it is called implicit Type conversion. Also known as automatic conversion println(2.myMax(6)) } }
Implicit parameter
Parameters in ordinary methods or functions can be declared as implicit parameters through the implicit keyword. When the method is called, the parameter can be passed in, and the compiler will find qualified implicit values in the corresponding scope.
(1) There can only be one implicit value of the same type in the same scope
(2) The compiler looks for the implicit value of the corresponding type according to the type of implicit parameter, which has nothing to do with the name of the implicit value.
(3) Implicit parameters take precedence over default parameters
object TestImplicitParameter { implicit val str: String = "hello world!" def hello(implicit arg: String="good bey world!"): Unit = { println(arg) } def main(args: Array[String]): Unit = { hello } }
Implicit class
Implicit classes must be defined in "class" or "companion object" or "package object", that is, implicit classes cannot be top-level.
object TestImplicitClass { implicit class MyRichInt(arg: Int) { def myMax(i: Int): Int = { if (arg < i) i else arg } def myMin(i: Int) = { if (arg < i) arg else i } } def main(args: Array[String]): Unit = { println(1.myMax(3)) } }
implicit var a = 1 def myTest():Unit = { println("---"+ implicitly[Int]) }
generic paradigm
class MyList[+T] {/ / covariant}
class MyList[-T] {/ / inversion}
class MyList[T] / / unchanged
Description covariance: if Son is a subclass of Father, MyList[Son] is also a "subclass" of MyList[Father].
Inversion: if Son is a subclass of Father, MyList[Son] is the "parent" of MyList[Father].
Unchanged: if Son is a subclass of Father, MyList[Father] and MyList[Son] have "no parent-child relationship".
Generic upper and lower bounds
Class personlist [T <: person] {/ / Generic upper limit}
Class personlist [t >: person] {/ / generic lower limit}
Int): MyRichInt = {
new MyRichInt(arg)
}
def main(args: Array[String]): Unit = {
//When you want to call an object function, if the compilation is wrong, the compiler will try to be in the current scope
Find the conversion rule that can call the corresponding function within the scope. This calling process is completed by the compiler, so it is called implicit
Type conversion. Also known as automatic conversion
println(2.myMax(6))
}
}
## Implicit parameter Parameters in ordinary methods or functions can be implicit Keyword is declared as an implicit parameter. When the method is called, the parameter can be passed in, and the compiler will find the qualified implicit value in the corresponding scope. (1)There can only be one implicit value of the same type in the same scope (2)The compiler looks for the implicit value of the corresponding type according to the type of implicit parameter, which has nothing to do with the name of the implicit value. (3)Implicit parameters take precedence over default parameters ```scala object TestImplicitParameter { implicit val str: String = "hello world!" def hello(implicit arg: String="good bey world!"): Unit = { println(arg) } def main(args: Array[String]): Unit = { hello } }
Implicit class
Implicit classes must be defined in "class" or "companion object" or "package object", that is, implicit classes cannot be top-level.
object TestImplicitClass { implicit class MyRichInt(arg: Int) { def myMax(i: Int): Int = { if (arg < i) i else arg } def myMin(i: Int) = { if (arg < i) arg else i } } def main(args: Array[String]): Unit = { println(1.myMax(3)) } }
implicit var a = 1 def myTest():Unit = { println("---"+ implicitly[Int]) }
generic paradigm
class MyList[+T] {/ / covariant}
class MyList[-T] {/ / inversion}
class MyList[T] / / unchanged
Description covariance: if Son is a subclass of Father, MyList[Son] is also a "subclass" of MyList[Father].
Inversion: if Son is a subclass of Father, MyList[Son] is the "parent" of MyList[Father].
Unchanged: if Son is a subclass of Father, MyList[Father] and MyList[Son] have "no parent-child relationship".
Generic upper and lower bounds
Class personlist [T <: person] {/ / Generic upper limit}
Class personlist [t >: person] {/ / generic lower limit}