文章目录

  • 写在前边的话
  • 一、变量和数据类型
    • 1、注释
    • 2、标识符的命名规范
    • 3、变量
    • 4、字符串
    • 5、键盘输入
    • 6、数据类型
    • 7、数字与字符串的转换
      • 1、数字与数字的转换
      • 2、数字与字符串的转换
  • 二、运算符
  • 三、流程控制
    • 1、块表达式:
    • 2、分支控制[if语句]
    • 3、for循环
    • 4、while、do-while循环
    • 5、break、continue
  • 四、函数式编程
    • 1、方法
      • 1、定义语法:
      • 2、方法的简化
      • 3、方法的参数
    • 2、函数
      • 1、定义
      • 2、高阶函数
      • 3、方法与函数的区别
      • 4、方法与函数的联系
      • 5、匿名函数
    • 6、函数柯里化与闭包
      • 7、递归
      • 8、控制抽象
      • 9、惰性求值
  • 五、面向对象
    • I、包
    • II、类和对象
      • 1、类
      • 2、封装 ********
      • 3、继承
      • 4、多态
      • 5、抽象类
      • 6、单例对象
      • 7、伴生类[class]和伴生对象[object]
      • 8、特质
      • 9、扩展
  • 六、集合
    • 集合常用函数
      • 1、基本属性
      • 2、衍生集合
      • 3、集合初级计算函数
      • 4、集合高级计算函数
      • 5、并行集合
  • 七、模式匹配
    • 1、定义语法:
    • 2、守卫
    • 3、匹配值
    • 4、匹配类型
    • 5、匹配数组
    • 6、匹配List
    • 7、匹配元组
    • 8、匹配对象和样例类
    • 9、变量声明与for循环模式匹配
    • 10、偏函数
  • 八、异常
  • 九、隐式转换
    • 1、隐式转换方法: 将一个类型转成另一个类型
    • 2、隐式参数: 在调用方法的时候给方法自动传参
    • 3、 隐式类: 将一个类型转成隐式类的类型
    • 4、隐式转换的解析机制:
  • 十、泛型
    • 1、泛型方法:
    • 2、泛型类:
    • 3、逆变、协变、非变
    • 4、泛型上下限
    • 5、上下文

写在前边的话

该笔记主要是自己回顾scala相关知识点的时候做的笔记,主要作为知识脉络整理,方便作为手册进行查看,没有源码内容,请君按需所取。

一、变量和数据类型

1、注释

 单行注释: //多行注释: /* .. */文档注释: /**...*/

2、标识符的命名规范

 scala的标识符命名的时候必须是字母、数字、下划线、$、一些特殊符号,不能以数字开头工作中对标识符命名的时候,特殊符号不推荐使用,是scala内部使用的工作中对变量命名的时候还是采用驼峰原则

3、变量

 1、定义语法: val/var 变量名:类型 = 值2、val与var的区别:val修饰的变量类似java final修饰的,不能修改值var修饰的变量类似java 非final修饰的,可以修改值3、scala在定义变量的时候,变量类型可以省略,scala会自动推断变量类型4、scala中如果一行只有一个语句,分号可以省略5、scala定义变量的时候必须初始化

4、字符串

 1、双引号包裹: val name = "lisi"2、通过new的方式创建: val name = new String("lisi")3、拼接1、通过+拼接: val name = "aa" + "bb"2、插值表达式: s"${变量名/值/表达式}"4、一些方法: subString,toString,format.."http://%s:%d".format(参数1,参数2)%s: 代表字符串的占位符%d: 代表整数的占位符%f: 浮点型的占位符5、三引号: """ .... """ [三引号一般用于sql语句]

5、键盘输入

 1、读取控制台数据: StdIn.readLine/readInt/readBoolean/..2、读取本地文件数据: Source.fromFile(path,encoding).getLines

6、数据类型

 Any: 所有类的父类AnyVal: 值类型Byte、Short、Char、Int、Long、Float、Double、BooleanUnit: 相当于java的void, 有一个实例()StringOps: 对java字符串的扩展AnyRef: 引用类型String、集合、数组、class..Null: 所有引用类型的子类,有一个实例null,一般用于给引用类型赋予初始值,此时必须定义变量类型Nothing: 所有类型的子类

7、数字与字符串的转换

1、数字与数字的转换

     1、低精度转高精度[Int->Long]: 自动转换2、高精度转低精度[Long->Int]: toXXX方法

2、数字与字符串的转换

     1、数字转字符串: toString/拼接2、字符串转数字: toXXX方法

二、运算符

1、算数运算符: + - * / %
2、关系运算符: < > <= >= == !=
3、逻辑运算符: && || !
4、赋值运算符: += -= *= /=
5、位运算符: << >> >>> & | ^
scala的运算符中没有++、--、三元运算符
scala中的运算符是一个个的方法,使用和java一样scala中方法调用的两种方式:1、对象.方法名(参数值,..)2、对象 方法名 (参数值,..) [如果只有一个参数,()可以省略]

三、流程控制

1、块表达式:

由{}包裹的一块代码称之为块表达式,块表达式有返回值,返回值是{}中最后一个表达式的结果值

后续基本上所有的{}包裹的代码都可以看做块表达式, for循环、while、do-while循环{}除外

2、分支控制[if语句]

1、单分支: if(布尔表达式){..}
2、双分支: if(布尔表达式){..} else {..}
3、多分支: if(布尔表达式){..} else if(布尔表达式){..} .. else {..}
scala中分支控制使用与java是一样
scala中if语句有返回值,返回值就是符合条件的分支的块表达式的结果值

3、for循环

for两个重要方法:to方法语法: start to end / start.to(end)to方法生成的集合是左右闭合的集合[包含start也包含end]until方法语法: start until end / start.until(end)until方法生成的集合是左闭右开的集合[包含start不包含end]
1、基本语法: for(变量名 <- 集合/数组/表达式) {循环体}
2、守卫: for(变量名 <- 集合/数组/表达式 if(布尔表达式)) {循环体} 【每次循环的时候只有if条件满足的时候才会执行循环体】
3、步长: for(变量名<- start to/until end by step) {循环体}
4、嵌套循环: for(变量名 <- 集合/数组/表达式;变量名 <- 集合/数组/表达式;..) {循环体}
5、循环之间嵌入变量: for(变量名 <- 集合/数组/表达式;变量名=值;变量名 <- 集合/数组/表达式;..) {循环体} 【嵌入变量之后,该变量可以在后续循环中使用】
6、for默认没有返回值,如果想要让for循环有返回值,可以使用yield表达式: for(变量名 <- 集合/数组/表达式) yield{循环体}

4、while、do-while循环

scala中while与do-while循环与java的while与do-while循环完全一样

5、break、continue

tips:scala中没有break与continue关键字,本质就是try()…catch{}

  • scala实现break功能:

      1、导入包: import scala.util.control.Breaks._2、通过breakable包裹循环,通过break方法跳出循环breakable({while(布尔表达式){..if(..) break()...}})
    
  • scala实现continue功能:

      1、导入包: import scala.util.control.Breaks._2、在循环中通过breakable包裹循环体代码,通过break方法结束本次循环while(布尔表达式){breakable({..if(..) break()..})}
    

四、函数式编程

1、方法

1、定义语法:

 def 方法名(参数名:类型,...):返回值类型 = {方法体}

2、方法的简化

1、如果要使用方法体块表达式的结果值作为方法的返回值,此时返回值类型可以省略注意: 如果在方法体中有return关键字的时候不能省略返回值类型
2、如果方法体只有一个语句,此时方法体的{}可以省略
3、如果方法不需要返回值,此时=可以省略
4、如果方法不需要参数,此时定义方法的是参数列表的()可以省略注意:1、如果定义方法的时候参数列表的()省略了,调用的时候也不能带上()2、如果定义方法的时候参数列表的()没有省略,此时调用的时候()可有可无

3、方法的参数

1、默认值参数[定义方法的时候可以给参数指定默认值,有默认值的参数后续在调用的时候可以不用传值]语法: def 方法名(参数名:类型 = 默认值,...):返回值类型 = {方法体}默认值参数一般放在参数列表最后面
2、带名参数[在方法调用的时候将值指定传递给哪个参数]def add(x:Int=10,y:Int) = x+yadd(y=20) //带名参数的调用
3、可变参数语法: def 方法名(参数名:类型,...,参数名:类型*):返回值类型 = {方法体}可变参数不能与默认值参数一起使用scala中可变参数不能直接传递数组、集合,如果想要将数组/集合的所有元素传递给可变参数可以通过 数组名:_* 的方式传递

2、函数

1、定义

 1、定义语法: val 函数名 = (参数名:类型,...) => {函数体}2、函数就是对象,函数名就是对象的引用3、调用函数的时候,参数列表的小括号不能省略4、函数的简化: 如果函数体中只有一行语句,此时函数体的{}可以省略5、函数是对象,函数的类型: (参数类型,...) => 返回值类型

2、高阶函数

1、定义: 以函数作为参数/返回值的函数/方法称之为高级函数
2、高阶函数的简化[是指高阶函数调用的时候简化]def add(x:Int,y:Int,func: (Int,Int)=>Int) = func(x,y)val func = (x:Int,y:Int) => x+yadd(10,20,func)1、直接传递函数值: add(10,20,(x:Int,y:Int) => x+y)2、函数的参数类型可以省略: add(10,20,(x,y) => x+y)3、如果函数的参数在函数体中只使用了一次,可以用_代替: add(10,20,_+_)以下三种情况不能用_代替:1、函数的参数定义顺序与使用的顺序不一致的时候,不能用_简化add(10,20,(x,y)=>y-x) 不能简化为 add(10,20,_-_) [因为第N个_代表第N个参数]2、函数体中有(),函数的参数在函数体的()中以表达式的形式存在的时候不能简化add(10,20,(x,y)=>(x+1)*y) 不能简化为 add(10,20,(_+1)*_)3、函数只有一个参数的时候,在函数体中没有做任何操作直接返回函数的参数,不能用_简化def m1(x:Int,func: Int => Int) = func(x)m1(10,x=>x) 不能简化为: m1(10,_)4、如果函数只有一个参数,参数列表的()可以省略m1(10,(x)=>x) 简化为 m1(10,x=>x)

3、方法与函数的区别

 1、方法定义在class/object里面的时候可以重载,函数是对象,函数名就是属性名,不可以重载2、方法定义在class/object里面的时候可以存储在方法区中,函数是对象存在堆中

4、方法与函数的联系

 1、方法如果定义方法里面就是函数,不能重载2、方法手动转成函数: 方法名 _

5、匿名函数

 1、定义: 没有函数名的函数称之为匿名函数2、匿名函数一般适用于高阶函数传参(x:Int)=> x * x

6、函数柯里化与闭包

 1、柯里化1、定义: 有多个参数列表的方法称之为柯里化2、语法: def 方法名(参数名:类型,..)(参数名:类型,..).. = {...}3、函数是对象,所以函数可以作为方法的返回值def add(x:Int) = {val f1 = (y:Int) => x+yf1}add(10)(20)2、闭包1、定义: 函数体/方法体中使用了不属于自身的变量的方法/函数称之为闭包val a = 10val func = (b:Int) => a+b

7、递归

1、定义: 自己调用自己称之为递归递归方法/函数有两个前提条件:1、必须要有退出条件2、必须的定义返回值类型
2、语法:1、递归方法: def m1(n:Int):Int = {if(n==1) 1 //退出条件else n * m1(n-1)}2、递归函数:val func: Int=>Int = (n:Int) => {if(n==1) 1else n * func(n-1)}

8、控制抽象

1、语法: =>返回值类型
2、控制抽象其实就是一个块表达式,控制抽象只能作为方法的参数类型存在,不能单独定义。控制抽象作为方法的参数存在的时候,代表后续调用方法的时候需要给控制抽象类型的参数传入一个块表达式,后续控制抽象在方法体中可以当做函数调用[在调用的时候不能带上()]def m1(x:Int,func: =>Unit) = {func //控制抽象调用func //控制抽象调用}m1(10,{.....})此时m1传入的块表达式不会立即执行,而是等到控制抽象调用的时候才会执行,调用一次执行一次

9、惰性求值

1、语法:lazy val 变量名 = 值
2、变量名通过lazy修饰之后不会立即初始化,而是等到变量真正使用的时候才会初始化

五、面向对象

I、包

1、导入包scala可以在任何地方导入包1、导入包下所有类: import 包名._2、导入包下某个类: import 包名.类名3、导入包下某个类,并起别名: import 包名.{类名=>别名}4、导入包下多个类: import 包名.{类名,类名,..}5、导入包下除开某个类的所有类: import 包名.{类名=>_, _}导入包的时候注意作用域问题: 在当前作用域导入的包只能在当前作用域以及子作用域使用
2、声明包声明包必须在源文件第一行语法: package 包名
3、创建包语法: package 包名{....}此种方式创建的包只能在classes目录下才能看到
4、包对象语法: package object 包名{....}包对象中定义的非private修饰的属性和方法可以在包下任何地方直接使用
5、包与访问修饰符结合语法: private[包名] val 变量名:类型 = 值private[包名]代表的是当前修饰的属性和方法/函数只能在指定包下使用

II、类和对象

1、类

1、语法: class 类名{..}
2、创建对象语法: new 类名(..)
3、定义属性和方法1、定义属性1、语法: [访问修饰符] val/var 属性名:类型 = 值2、var修饰的属性可以使用_赋予初始值[使用_赋予初始值的时候,属性的类型必须定义] var name:String = _3、val修饰的属性不可修改值,var修饰的属性可以修改值2、定义方法:语法: [访问修饰符] def 方法名(参数名:类型,..):返回值类型 =  {...}
4、构造器scala的构造器分为两大类: 主构造器、辅助构造器主构造器1、定义位置: 定义在class类名后面通过()表示2、语法: class 类名([访问修饰符] [val/var] 属性名:类型 [= 默认值],...){...}主构造器中val/var修饰的属性与不用val/var修饰的属性的区别:val/var修饰的非private的属性可以在class内部和外部使用不用val/var修饰的属性只能在class内部使用辅助构造器1、定义位置: 定义class内部2、语法:def this(参数名:类型,...){//辅助构造器第一行必须调用其他的辅助构造器或者是主构造器this(..)}

2、封装 ********

 java很多api底层都需要java的set/get方法,scala为了兼容java提供了一个注解@BeanProperty,该注解能够自动生成java的set/get方法

tips:@BeanProperty注解不能用于private修饰的属性

3、继承

 1、语法: class 子类 extends 父类2、final修饰的class不能被继承3、父类中private修饰的成员不能被继承4、子类可以通过override关键字重写父类的方法/val修饰的属性5、var修饰的属性不能被重写6、子类可以通过super关键字调用父类的方法

4、多态

 scala中属性与方法都是多态的

5、抽象类

 1、语法: abstract 类名{...}2、抽象类中既可以定义抽象方法也可以定义具体方法既可以定义抽象属性也可以定义具体属性3、抽象方法: 没有方法体的方法称之为抽象方法【定义抽象方法的时候如果方法没有定义返回值类型,默认是Unit类型】4、抽象属性: 没有初始化的属性称之为抽象属性5、匿名子类:new 抽象类类名{//重写抽象属性与方法}

6、单例对象

 1、创建语法: object object名称{..}2、获取单例的对象: object名称3、object中定义的所有的属性和方法都是类似java static修饰的,可以通过 object名称.方法/属性 调用4、class中定义的所有的属性和方法都是类似java 非static修饰的

7、伴生类[class]和伴生对象[object]

 前提:1、class与object同名2、class与object在同一个源文件中class Person{}object Person{}特性: 伴生类和伴生对象可以互相访问对象private修饰的成员apply方法:1、定义: 必须定义在伴生对象中2、作用: 为了简化伴生类对象的创建有了apply方法之后,如何创建伴生类对象: object名称.apply(..) /object名称(..)

8、特质

scala是单继承,多实现

1、语法: trait 特质名{...}
2、抽象类中既可以定义抽象方法也可以定义具体方法既可以定义抽象属性也可以定义具体属性
3、子类如何实现特质1、子类需要继承父class: 此时extends关键字用于继承父class,特质的实现通过with关键字2、子类不需要继承父class: 此时extends关键字用于实现第一个特质,其他特质的实现使用with关键字
4、对象混入:1、定义:让某个对象拥有指定特质的属性/方法2、语法: new 类名(..) with 特质名
5、特质的叠加scala可以实现多个特质,如果这多个特质中都有一个同名方法,参数列表也一样,此时子类继承之后调用的时候默认报错,可以通过在子类中重写同名方法解决该问题。如果在子类重写的同名方法中通过super关键字调用的时候,默认调用的时候最后一个特质的同名方法如果想要调用指定父特质的同名方法,可以通过 super[父特质名].同名方法 的形式调用。如果这多个父特质都继承同一个特质,此时又有通过super调用同名方法,此时调用顺序是按照继承顺序从右向左开始调用
6、自身类型1、语法: this:类型 => [是定义在特质里面的]2、作用: 提醒子类在继承triate的时候必须先继承/实现指定类型

9、扩展

1、类型检查和判断1、判断对象是否属于某个类型: 对象.isInstanceOf[类型]2、将对象强转为某个类型: 对象.asInstanceOf[类型]3、获取对象的class形式: 对象.getClass()4、获取类的class形式: classOf[类名]
2、type定义新类型: 给指定类型起别名语法: type 别名 = 类型

六、集合

scala中集合分为两大类: 可变集合、不可变集合

  • string属于不可变集合
  • 可变数组在 scala.collection.mutable 包中
  • 不可变数组在 scala.collection.immutable 包中

可变集合: 集合长度可变[可以添加/删除数据]

可变数组:1、创建方式:1、通过new的方式创建: new ArrayBuffer[元素类型]()2、通过apply方法: ArrayBuffer[元素类型](初始元素,....)2、可变数组转不可变数组: toArray
可变List:1、创建方式:1、通过new的方式创建: new ListBuffer[元素类型]()2、通过apply方法: ListBuffer[元素类型](初始元素,....)
可变Set:Set里面的元素是不重复、无序的1、创建方式:通过apply方法: mutable.Set[元素类型](初始元素,....)Set不能根据角标获取元素以及修改元素
可变Map:1、创建方式:通过apply方法: mutable.Map[K的类型,V的类型]( K->V, (K,V),... )2、添加元素:put方法: put(k,v)3、删除元素:remove方法: remove(key)4、获取元素: getOrElse(key,默认值) 【如果key在map中不存在则返回默认值,如果key存在则返回key的value值】Option类型: 提醒外部当前结果有可能为空需要进行处理Option有两个子类:Some: 代表不为空[结果数据封装在Some对象中]None: 代表为空
可变队列1、创建方式: mutable.Queue[元素类型](初始元素,...)2、添加数据: enqueue3、删除数据: dequeue

不可变集合: 集合长度不可变[不能添加/删除数据]

不可变数组:1、创建方式:1、通过new的方式创建: new Array[元素类型](集合长度)2、通过apply方法: Array[元素类型](初始元素,....)2、不可变数组转可变数组: toBuffer3、创建多维数组: Array.ofDim(行数,列数)
不可变List:1、创建方式:1、通过 :: 方法创建 : 初始元素 :: 初始元素 .... :: Nil/不可变ListNil其实就是一个空的不可变List,Nil与不可变List的关系类似Null与String的关系所以,Nil一般用于给不可变List赋予初始值,在赋予初始值的时候变量类型必须定义2、通过apply方法: List[元素类型](初始元素,....)2、添加元素::  用于添加单个元素::: 用于添加一个不可变List里面的所有元素
不可变Set:Set里面的元素是不重复、无序的1、创建方式: 通过apply方法: Set[元素类型](初始元素,....)Set不能根据角标获取元素以及修改元素
不可变Map:1、创建方式:通过apply方法: Map[K的类型,V的类型]( K->V, (K,V),... )2、获取元素: getOrElse(key,默认值) 【如果key在map中不存在则返回默认值,如果key存在则返回key的value值】
不可变队列队列特性: 先进先出,有序的1、创建方式: immutable.Queue[元素类型](初始元素,...)2、添加数据: enqueue3、删除数据: dequeue

集合通过的添加/删除元素的方法[+、+:、:+、+=、+=:、++、++:、++=、++=:、-、–、-=、–=]

1、带+与带-的区别:带+是添加元素,带-是删除元素
2、带=与不带=的区别带=是修改集合本身 【带=的方法只有可变集合才有】不带=是生成新集合,原集合没有改变
3、冒号在前、冒号在后以及不带冒号的区别冒号在前是将元素添加在集合最末尾冒号在后是将元素添加在集合最前面不带冒号试将元素添加在集合最末尾
4、两个+/-与一个+/-的区别两个+/-是添加/删除一个集合所有元素一个+/-是添加/删除单个元素
5、update与updated的区别update是修改集合本身updated是生成新集合,原集合没有改变

元组:

1、定义语法1、所有元组都通用的创建方式: (初始元素,初始元素,..)2、只适用于二元元组的创建方式: K -> V
2、元组中最多只能存放22个元素
3、元组一旦定义元素以及长度都可以改变
4、元组的取值: 元组名._角标 [元组的角标从1开始的]

集合常用函数

1、基本属性

 1、判断集合是否为空: isEmpty2、获取集合长度: length/size3、判断是否包含某个元素: contains(元素)4、将集合所有元素转换成字符串: mkString(分隔符)5、集合转成迭代器: 集合名.iterator

2、衍生集合

 1、去重: distinct2、获取集合第一个元素: head3、获取集合最后一个元素: last4、获取除开第一个元素的其他所有元素: tail5、获取除开最后一个元素的其他所有元素: init6、获取除开前N个元素的其他所有元素: drop(N)7、获取除开最后N个元素的其他所有元素: dropRight(N)8、获取前N个元素: take(N)9、获取后N个元素: takeRight(N)10、获取指定角标范围的子集合: slice(from,until) [子集合不包含Until角标的元素]11、滑窗: sliding(size,step)size: 窗口的大小step: 滑动的长度12、交集[两个集合共同的元素]: list1.intersect(list2)13、差集[A差B的结果就是A中有B中没有的元素]: list1.diff(list2)14、并集[合并两个集合]: list1.union(list2)15、拉链: zip16、反拉链[要求集合中元素二元元组]: unzip17、将元素与角标拉链:zipWithIndex18、反转: reverse

3、集合初级计算函数

 1、获取最大值: max2、获取最小值: min3、求和: sum4、根据指定字段获取最大值: maxBy(func: 集合元素类型 => B)maxBy是根据函数的返回值取最大值maxBy里面的函数是针对集合每个元素进行操作5、根据指定字段获取最小值: minBy(func: 集合元素类型 => B)minBy是根据函数的返回值取最小值minBy里面的函数是针对集合每个元素进行操作6、排序1、sorted: 根据元素本身排序 【默认升序】如果集合元素是数字则直接按照数字排序如果集合元素是字符串则按照字典序排序如果集合是元组则首先按照元组的第一个元素排序,如果第一个元素相同则按照第二个元素排序2、sortBy(func: 集合元素类型 => B ): 根据指定字段排序【默认升序】sortBy里面的函数针对集合每个元素进行操作sortBy排序是根据函数的返回值进行排序3、sortWith(lt: (集合元素类型,集合元素类型) => Boolean): 指定排序规则升序: 第一个参数<第二个参数降序: 第一个参数>第二个参数

4、集合高级计算函数

 1、map(func: 集合元素类型 => B ): 映射【一对一的映射】map里面的函数是针对集合每个元素进行操作,操作完成之后会返回一个结果 【一个元素对应一个结果】map有返回值,一个集合通过map计算之后会生成一个新的集合:  val A = B.map(..) ,此时A集合的元素个数=B集合元素个数map的应用场景: 一对一,一般用于数据类型的转换或者是值的转换val list2 = List(1,2,3,4,5).map(x=>x*x)list2结果: List(1,4,9,16,25)2、flatten: 压平flatten是压平第二层集合: List[List[List[Int]]].flatten之后的数据类型 = List[List[Int]]flatten只能用于集合嵌套集合的数据类型flattne的应用场景: 一对多3、flatMap(func: 集合元素类型 => 集合) = map + flattenflatMap里面的函数针对集合每个元素进行操作flatMap的应用场景: 一对多flatMap与flatten的区别:flatMap是先对数据进行转换之后再压平flatten是单纯的压平,没有数据的转换操作4、groupBy(func: 集合元素类型=>K):按照指定字段分组groupBy里面的函数针对集合每个元素进行操作groupBy是按照函数的返回值进行分组groupBy的结果是Map[K,V]map中的K是函数的返回值map中的V是K对应原集合中的所有元素groupBy的应用场景: 多对一5、foreach(func: 集合元素类型 => B):Unit  : 遍历元素执行指定操作foreach与map的唯一区别:map计算完成之后会生成一个新的集合foreach计算完成之后没有返回值foreach类似普通for循环,map类似yield的for循环6、filter(func: 集合元素类型 => Boolean ): 根据指定条件过滤filter里面的函数是针对集合每个元素操作filter保留的是函数返回值为true的数据7、reduce(func: (集合元素类型,集合元素类型)=>集合元素类型): 按照指定逻辑从左向右聚合reduce里面的函数是针对每两两个元素计算reduce里面的函数在第一次计算的时候,第一个参数的值 = 集合第一个元素reduce里面的函数在第N次计算的时候,第一个参数的值 = N-1次的计算结果8、reduceRight(func: (集合元素类型,集合元素类型)=>集合元素类型): 按照指定逻辑从右向左聚合reduceRight里面的函数是针对每两两个元素计算reduceRight里面的函数在第一次计算的时候,第二个参数的值 = 集合最后一个元素reduceRight里面的函数在第N次计算的时候,第二个参数的值 = N-1次的计算结果9、fold(默认值)(func: (集合元素类型,集合元素类型)=>集合元素类型): 按照指定逻辑从左向右聚合fold与reduce类似,与reduce唯一的区别在于: fold里面的函数在第一次计算的时候,第一个参数的值 = 默认值10、foldRight(默认值)(func: (集合元素类型,集合元素类型)=>集合元素类型): 按照指定逻辑从右向左聚合foldRight与reduceRight类似,与reduceRight的唯一区别在于: foldRight里面的函数在第一次计算的时候,第二个参数的值 = 默认值

5、并行集合

 普通List、Array等集合都是单线程操作,如果想要多线程操作集合元素需要将普通集合转成并行集合: 集合名.par

七、模式匹配

1、定义语法:

 变量名 match {case 条件 => {...} //{}可以省略case 条件 => ... ...case x => ... //类似switch的default,可以匹配其他所有情况//如果x在=>右边不使用可以用_代替//case _ => ..}模式匹配有返回值,返回值就是符合条件的分支的块表达式的结果值

2、守卫

 有了守卫之后,不许同时满足case条件与守卫要求才算能够匹配上变量名 match {case 条件 if(布尔表达式) => {...} case 条件 if(布尔表达式) => ... ...case x if(布尔表达式) => }

3、匹配值

 变量名 match {case 值1 => ..case 值2 => ..case 值3 => ......}模式匹配的case匹配条件中如果想要使用外部的变量的值,此时变量名必须首字母大写val Name = "hadoop"param match {case Name => ... //此时Name代表hadoop字符串case name => .. //该name就是局部变量不是代表hadoop}

4、匹配类型

 变量名 match {case x:类型1 => ..case x:类型2 => ..case x:类型3 => .....}

5、匹配数组

 变量名 match {case Array(x) => println(匹配数组只有一个元素)case Array(x,y,z) => println(匹配数组只有三个元素)case Array(x,_*) => println(匹配数组至少有一个元素)}

6、匹配List

 第一种匹配方式:变量名 match {case List(x) => println(匹配数组只有一个元素)case List(x,y,z) => println(匹配数组只有三个元素)case List(x,_*) => println(匹配数组至少有一个元素)}第二种匹配方式:变量名 match {case x :: Nil => println(匹配数组只有一个元素)case x :: y :: z :: Nil => println(匹配数组只有三个元素)case x :: tail => println(匹配数组至少有一个元素) [tail与x一样都是一个局部变量,代表的是除开前面元素的其他所有元素集合]}

7、匹配元组

 val t = ("xx",20,"senzhen")t match {case (x,y,z) => ...}变量是几元元组,匹配条件中就只能是几元元组

8、匹配对象和样例类

 样例类: 其实就是伴生对象和伴生类的封装语法: case class 类名([val/var] 属性名:类型,...)属性名如果不用val/var修饰,默认就是val修饰的如何通过样例类创建对象: 样例类的类名(值,..)case class Person(val name:String,var age:Int)val person = Person("zhangsan",20)样例类可以直接用于模式匹配.persom match {case Person(name,age) => ...}普通类不能直接用于模式匹配,如果想要让普通类用于模式匹配需要在伴生对象中定义unapply方法[unapply方法就是将对象解构成属性]class Student(val name:String,var age:Int)object Student{def apply(String name,Int age) = new Student(name,age)def unapply(arg:Student):Option[(String,Int)] = {if(arg==null) Noneelse Some((arg.name,arg.age))}}val student = Student("lisi",30)student match{case Student(name,age) => ..}

9、变量声明与for循环模式匹配

 val (name,age) = ("lisi",20)val List(x,_*) = List(1,5,3,7)val map = Map("xx"->10,"yy"->20)for( (key,value)<- map ){....}

10、偏函数

 1、定义: 没有match关键字的模式匹配称之为偏函数2、语法: val func: PartialFunction[IN,OUT] = {case 条件 => .......}IN: 代表模式匹配参数类型OUT: 代表模式匹配返回值类型偏函数也是一个函数,所以工作中一般会将偏函数结合map、flatMap、groupBy等一起使用val list = List( ("xx",10),("yy",20))list.map{case (name,age) => (name,age * age)}

八、异常

scala中对于异常的处理方式有两种:1、捕获异常1、try{..}catch{..}finaly{...} [此种方式一般在工作中只用于获取外部链接[mysql链接]的时候]2、Try(代码块).getOrElse(默认值) 【如果代码块执行成功,则返回代码块执行结果,如果代码执行失败则返回默认值】2、抛出异常 【工作不用】scala在方法体中可以通过throw关键字抛出异常,不需要在方法名后面通过throws声明异常

九、隐式转换

1、隐式转换方法: 将一个类型转成另一个类型

语法: implicit def 方法名(参数名:待转换类型):目标类型 = {...}
隐式转换方法的调用时机:1、当前类型与目标类型不一致的时候: val a:Int = 10.0 [此时scala会查询是否有符合条件的隐式转换方法能够将Double转成Int]2、当对象使用了不属于自身的属性或者方法/函数的时候: val file = new File("..")file.getLines() 【file不具有getLines方法,所以此时scala会查询是否有符合条件的隐式转换能够将File对象转成一个特定对象,该对象拥有getLines方法】

2、隐式参数: 在调用方法的时候给方法自动传参

语法:1、在定义方法的时候指定后续哪个参数会自动传参: def 方法名(参数名:类型,..)(implicit 参数名:类型) = {...} [implicit标识的参数后续可以自动传参]2、指定后续传给隐式参数的值是多少: implicit val 参数名:类型 = 值
implicit val x:Int = 10
def m1(a:Int)(implicit b:Int) = a+b
m1(20) //此时m1的b参数,scala会自动将x传递给b

3、 隐式类: 将一个类型转成隐式类的类型

语法: implicit class 类名(属性名:待转换类型){...}
隐式类的必须要有一个特定的主构造器【该主构造器有一个参数,参数类型就是待转换类型】
后续scala会自动调用该柱构造器创建隐式类型,所以就达到了将待转换类型转成隐式类类型
隐式类不能置于最顶层,必须定义在object/class中

4、隐式转换的解析机制:

scala会首先从当前作用域以及父作用域查询是否有符合条件的隐式转换,如果有直接使用,如果没有会报错。如果隐式参数定义在其他的object中,后续需要使用的时候需要通过 import object名称._ / import object名称.隐式转换名称 导入使用。如果隐式参数定义在其他的class中,后续需要使用的时候需要通过 import 对象._ / import 对象.隐式转换名称 导入使用。
如果scala查询到有多个隐式转换都满足要求的时候,需要指定使用哪个隐式转换【import object名称.隐式转换名称/import 对象.隐式转换名称】

十、泛型

1、泛型方法:

def 方法名[T,U,..](参数名:T):U = {...}

2、泛型类:

class 类名[T,U,..](属性名:T,..)={def 方法名(参数名:U) = {..}
}
泛型类中的方法/属性都是可以使用类名后面定义的泛型

3、逆变、协变、非变

逆变[-T]: 通过泛型创建对象之间颠倒了泛型的父子关系
协变[+T]:通过泛型创建对象之间继承了泛型的父子关系
非变[T]: 通过泛型创建对象之间没有任何关系

4、泛型上下限

上限[T<:类型] : 代表泛型必须是指定类型或者是子类
下限[T>:类型] : 代表泛型必须是指定类型或者是父类

5、上下文

语法: T:类型
def 方法名[T:Person](x:T) = {val p = implicity[Person[T]]
}
等价于
def 方法名[T](x:T)(implicit p:Person[T]) = {...}

详尽全面而又简单易懂的Scala学习笔记(参上)【不适合零基础】相关推荐

  1. 【PM学习笔记】酸梅干超人 - 零基础学Figma学习笔记

    原视频链接: B站视频 零基础学Figma学习笔记 心得体会 第1课 - 苹果商店页设计 第2课 - 线性图标设计 第3课 - 面性图标设计 第4课 玻璃拟态页设计 第5课 样式组件功能入门 第6课 ...

  2. 【PM学习笔记】酸梅干超人 - 零基础学B端UI设计 学习笔记

    学习笔记目录 0 先导片 1.1 B端是什么?和C端有什么区别? 1.2 完整走一遍B端项目流程 1.3 B端产品经理介绍 PM都在做什么? 0 先导片 B端业务类型 举例:云服务.智慧系统.数据BI ...

  3. 全网完整版Python学习路线图(超详细适合零基础自学)

    本文包含了千锋教育Python学习路线全阶段视频教程(从入门到精通),涵盖了你所需要掌握的所有前沿技术及知识点! 全网最新,史上最全Python学习路线,从基础到项目实战应有尽有,牛批卡拉斯! Pyt ...

  4. 学习笔记(01):8小时Python零基础轻松入门-类

    立即学习:https://edu.csdn.net/course/play/29122/408297?utm_source=blogtoedu 类(class)是一种面向对象计算机编程语言的构造,是创 ...

  5. 学习笔记(02):8小时Python零基础轻松入门-实例和属性

    立即学习:https://edu.csdn.net/course/play/29122/408306?utm_source=blogtoedu 类属性,又称静态属性 类属性只有通过类才能修改 实例也拥 ...

  6. Scala 学习笔记

    Scala 学习笔记 1 object func_exp { 2 println("Welcome to the Scala worksheet") //> Welcome ...

  7. Scala学习笔记04:内建控制结构

    Scala学习笔记04:内建控制结构 scala提供的控制结构并不算多,因为在函数式编程中,可以自己开发出各种功能的控制结构,所以scala提供的原生控制结构仅仅够用为止. 1.if - 判断 if是 ...

  8. Scala学习笔记03:操作符

    Scala学习笔记03:操作符 一.scala中操作符与方法的等价性 scala中操作符即方法.方法即操作符.scala中操作符其实是普通方法调用的另一种表现形式,运算符的使用其实就是隐含地调用对应的 ...

  9. Scala学习笔记02:数据类型、常量与变量

    Scala学习笔记02:数据类型.常量与变量 一.数据类型 1.基本数据类型 Byte 字节型 Short 短整型 Int 整型 Long 长整型 Char 字符型 String 字符串 Float ...

最新文章

  1. [Buzz.Today]2011.05.25
  2. 【Verilog HDL 训练】第 01 天
  3. Android Activity的launchMode四种启动模式备忘
  4. python快速入门 pdf-十分钟快速入门python
  5. 浅谈数据库优化方案--表和SQL
  6. 【NLP】 深入浅出解析BERT原理及其表征的内容
  7. Java ArrayDeque
  8. input 0.1无法相加_你真的知道0.1+0.2为何不等于0.3吗?
  9. JDK8 Stream 操作
  10. 介绍家乡网页html代码_「HTML一」 html基础
  11. Spring MVC JSR-303验证框架之Hibernate-Validator
  12. android之StrictMode介绍
  13. 锐炬显卡和独立显卡有什么不同?
  14. 【分享】.Net有哪些大型项目、大型网站的案例?
  15. torch学习 (二十九):周杰伦歌词数据集测试循环神经网络
  16. MMDetection亲测安装教程
  17. 基于node.js + ElementUI 的sass人力资源后台管理系统的实现
  18. python dialect='excel'是什么意思_python excel自动化写入大数据量数据
  19. HTML学习笔记(五)
  20. 华为鸿蒙系统英语报纸_华为鸿蒙系统报名方法

热门文章

  1. Successfully deployed.Backed up previous deployment.
  2. 今天面了一个大学生:这82道SpringBoot面试题都答不上来?还想进大厂?
  3. EF中的TPH、TPT、TPC
  4. 什么是长连接,什么是短连接
  5. 反三角函数之间的关系以及导数关系
  6. PEMFC燃料电池机理模型
  7. 程序员必备软件清单,没时间解释了,快上车
  8. 编制计算机程序的算法是什么,中国大学MOOC: 编制计算机程序解决问题的过程有:描述问题、算法设计、编写计算机程序和调试等,其中对算法描述不正确的是()。...
  9. 小程序Cannot set property 'userInfo' of undefined
  10. 看到一篇好的文章计算机专业的学习心得