Scala
一 scala简介
六大特性
1 java和scala可以混编
2 类型推测(自动推测类型)
3 并发和分布式
4 特质,特质
5 模式匹配
6 高阶函数
scala应用
kafka :分布式消息队列,内部代码经常用来处理并发的问题,用scala可以大大简化其代码。
spark :方便处理多线程场景,另外 spark 主要用作内存计算,经常要用来实现复杂的算法。利用
scala 这种函数式编程语言可以大大简化代码。
二scala安装
windows安装
http://spark.apache.org/docs到里面找对应spark版本的文档进行查看
下载
官网下载scala2.12:
https://www.scala-lang.org/download/2.12.11.html
**
**
环境变量
配置方法同 jdk 配置方式。
验证
打开 cmd ,输入: scala -version 看是否显示版本号,确定是否安装成功
idea配置scala插件
第一步:打开 idea ,点击 Configure->Plugins(打开的项目可以在这里找)
第二步:搜索 scala ,点击 Install 安装,第一次安装完成后会要求重启 ide 。
第三步:设置新建项目的默认设置
环境配置
第一步:设置你的 jdk
第二步:选中你对应 jdk 安装路径即可
最终如图所示即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jlutf63k-1662554948020)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1662362738024.png)]
创建项目
第一步:创建基础 scala 项目,配置 scala sdk(Software Development Kit)
=blog.csdnimg.cn/4758d62be0ce47d39757288b15bc257c.png)
第二步:点击 Browse 选择本地安装的 Scala 目录即可
三scala基础
数据类型
变量和常量
- 变量 :用 var 定义 ,可修改
- 常量 :用 val 定义,不可修改
运算符
- 算术运算符
+ - * / %
关系运算符
== != > < >= <=
逻辑运算符
&& || !
位运算符
& | ^= += -= *= /= %= <<= >>= &= ^= |=
函数与方法
方法:
- def关键字
- 返回值类型可以不写return,如果有显示return则 要写
- 去掉方法体前的unit,scala可以把任意类型转换为unit
- scala规定方法传过来的参数为val不是var
函数:
- scala是基于Function家族的,一共有23个Function Trait可以被使用,数字代表Function的入参个数
- 函数可以直接赋值给变量,可以让函数很方便的传递
方法与函数
- 对java来说函数和方法是等价的,或者说没有函数这个概念,对于scala有一个明确的边界
- scala方法是类的一部分,而函数是一个对象,对象的引用可以赋值给一个变量,换句话说在类中定义的函数是方法
- val定义函数,def定义方法
区别:
- 函数定义在类中就为方法,其他的是函数
- 函数可以作为一个参数传到方法中,方法不可以
- scala不能直接操作方法,要先转换为函数,val f =m _表示m方法转为函数
闭包
- 闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量
- 闭包通常来讲可以简单的认为是可以访问一个函数里面的另外一个函数
字符串
- scala本身没有String
- scala中可以使用StringBuilder创建一个可以修改的字符串
- += ‘’ ++=“” :=
数组
创建数组:
new Array[String](3) 直接Array
类和对象
构造器
每个类都有一个主要的构造器,这个构造器是与类定义交织在一起的,一个是类的定义,一个是构造函数的定义
除了主构造器外,类还有任意多的辅助构造器,辅助构造器的名称为this
每个辅助构造器都必须以一个对先前已定义的其他辅助构造器或主构造器的调用开始
属性
如果被val修饰默认拥有getter方法
如果被private修饰getter,setter方法也被私有
可以使用@BooleanBeanProperty注解增加Java方式的getter和setter
嵌套类
可以在函数中定义函数,在类中定义类
伴生类和伴生对象
可以使用@BooleanBeanProperty注解增加Java方式的getter和setter
类和它的伴生对象可以互相访问其私有成员
继承
scala使用extends关键字来继承一个类,scala只允许继承一个父类
子类重写超类不用override
重写一个非抽象方法必须用override
Trait
trait与类相似,结果看来是实现了多继承
继承的多个trait中如果有同名的方法和属性,必须要在类中使用 override 重新定义。
trait中不可以带参数
构造器的执行顺序:
- 调用超类的构造器;
- 特征构造器在超类构造器之后、类构造器之前执行;
- 特征由左到右被构造;
- 每个特征当中,父特征先被构造;
- 如果多个特征共有一个父特征,父特征不会被重复构造
- 所有特征被构造完毕,子类被构造。
修饰符
scala中的修饰符有private,protected,public
外层类不能访问被嵌套内的私有成员
特殊符号使用
=>
表示函数的返回类型(Function Type)
当只有一个参数的时候,函数类型里面括起来函数参考的括号可以省略
匿名函数
by-name parameters
_
作为通配符,类似Java中的*. 如 import scala.math._
:_*作为一个整体,告诉编译器你希望将某个参数当做参数序列处理
参数传递
传值调用(call-by-value):先计算参数表达式的值,再应用到函数内部;
传名调用(call-by-name):将未计算的参数表达式直接应用到函数内部
四Scala函数深化
指定参数名
不需要按照顺序向函数传递参数
可变参数
最后一个参数可以是重复的,Scala 通过在参数的类型之后放一个星号来设置可变参数(可重复的参数)
递归函数
自己调用自己
必须有程序的出口
默认参数值
调用函数的过程中如果没有传递参数,函数就会调用它的默认参数值,
调用函数的过程中如果传递了参数,则传递值会取代默认值。
匿名函数
可以将匿名函数返回给val定义的值
匿名函数不能显式声明函数的返回类型
高阶函数
操作其他函数的函数
函数的参数是函数
函数的返回是函数
函数的参数和函数的返回是函数
柯里化函数
柯里化(Currying)指的是将原来接受两个参数的函数变成新的接受一个参数的函数的过程。
新的函数返回一个以原有第二个参数为参数的函数。
五Scala集合深化
scala.collection.immutable中的所有集合。不变的
scala.collection.mutable中的所有集合。可变的
Trait Map
Map是一种可迭代的键值对结构。Scala的Predef类提供了隐式转换,允许使用另一种语法:key ->value 代替(key,value)
list
不要忘记 Nil 是 长度为0的List 。
- filter :过滤元素
- count :计算符合条件的元素个数
- map :对元素操作
- flatmap :压扁扁平,先map再flat
Set
Scala Set(集合)是没有重复的对象集合,所有的元素都是唯一的
Scala 集合分为可变的和不可变的集合。
默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用scala.collection.mutable.Set 包。
元组Tuple
大体与列表一样,不同的是元组可以包含不同类型的元素。元组的值是通过将单个的值包含在圆括号中构成的。
取值用 ._X 可以获取元组中的值
Option
Scala Option(选项)类型用来表示一个值是可选的(有值或无值)。
getOrElse() 方法来获取元组中存在的元素或者使用其默认的值
isEmpty() 方法来检测元组中的元素是否为 None
WordCount
strings.flatMap(.split(" ")).map((,
1)).groupBy(.1).mapValues(.size).toList.sortBy(._2).foreach(println)
六模式匹配
一个模式匹配包含了一系列备选项,每个都开始于关键字 case 。
每个备选项都包含了一个模式及一到多个表达式。箭头符号 => 隔开了模式和表达式。
1.模式匹配不仅可以匹配值,还可以匹配类型
2.模式匹配中,如果匹配到对应的类型或值,就不再继续往下匹配
3.模式匹配中,都匹配不上时,会匹配到 case _ ,相当于default
偏函数
Scala中的Partia Function是一个Trait,其的类型为PartialFunction[A,B],其中接收一个类型为A的参数,返回一个类型为B的结果
一个 case 语句就可以理解为是一段匿名函数。
isDefinedAt : 这个函数的作用是判断传入来的参数是否在这个偏函数所处理的范围内。
orElse : 将多个偏函数组合起来使用,效果类似case语句。
andThen: 相当于方法的连续调用,比如g(f(x))。
applyOrElse:它接收2个参数,第一个是调用的参数,第二个是个回调函数。如果第一个调用的参数匹配,返回匹配的值,否则调用回调函数。
七样例类case class
apply:不需要使用new关键字就能创建该类对象
unapply :可以通过模式匹配来获取类属性,是Scala中抽取器的实现和模式匹配的关键方法
八隐式转换
1.将方法或变量标记为implicit
2.将方法的参数列表标记为implicit
3.将类标记为implicit
Scala隐式值
将p变量标记为implicit,所以编译器会在方法省略隐式参数的情况下去搜索作用域内的隐式值作为缺少参数
Scala隐式视图
隐式转换函数是指在同一个作用域下面,一个给定输入类型并自动转换为指定返回类型的函数,这个函数和函数名字无关,和入参名字无关,只和入参类型以及返回类型有关。注意是同一个作用域。
隐式转换为目标类型:把一种类型自动转换到另一种类型
隐式转换调用类中本不存在的方法
Scala隐式类
使用 implicit 关键字修饰的类就是隐式类。若一个 变量A 没有某些方法或者某些变量时,而这个 变量A 可以调用某些方法或者某些变量时可以定义一个隐式类,隐式类中定义这些方法或者变量,隐式类中传入 A 即可。
隐式类必须定义在类,包对象,伴生对象中。
隐式类的构造必须只有一个参数,同一个类,包对象,伴生对象中不能出现同类型构造的隐式
类。
Scala隐式参数
列表中可以添加隐式 implicit 关键字进行标记, 标记为 implicit 的参数在调用中可以省略
Scala编译器会从当前作用域中寻找一个相同类型的隐式变量,作为调用参数
注意
同类型的参数的隐式值只能在作用域内出现一次,同一个作用域内不能定义多个类型一样的隐式值。
implicit 关键字必须放在隐式参数定义的开头
一个方法只有一个参数是隐式转换参数时,那么可以直接定义 implicit 关键字修饰的参数,调用时直接创建类型不传入参数即可。
一个方法如果有多个参数,要实现部分参数的隐式转换,必须使用柯里化这种方式,隐式关键字
出现在后面,只能出现一次
Actor Model
并行计算或分布式系统的高层次抽象, Actors 将状态和行为封装在一个轻量的进程/线程中,每个 Actors 有自己的世界观,当需要和其他 Actors 交互时,通过发送事件和消息,发送是异步的,非堵塞的(fire-andforget),发送消息后不必等另外 Actors 回复,也不必暂停,每个 Actors 有自己的消息队列,进来的消息按先来后到排列,这就有很好的并发策略和可伸缩性,可以建立性能很好的事件驱动系统。
Actor的特征
ActorModel 是消息传递模型,基本特征就是消息传递
消息发送是异步的,非阻塞的
消息一旦发送成功,不能修改
Actor 之间传递时,接收消息的 actor 自己决定去检查消息, actor 不是一直等待,是异步非阻塞的
Actor发送接收消息
Actor与Actor之间通信
问题
var,val和def三个关键字之间的区别
答:val声明常量,var声明变量,def 方法声明
object和class的区别?伴生对象是什么?
答:object是类的单例对象(static关键字),无序new关键字实例化,对象名字与类名相同的时候这个对象是伴生对象。伴生对象可以访问类中的私有量,类也可以访问伴生对象中的私有方法。
Scala类型系统中Nil, Null, None, Nothing四个类型的区别?
Null是⼀个trait(特质),是所以引⽤类型AnyRef的⼀个⼦类型, null是Null唯⼀的实例。Nothing也是⼀个trait(特质),是所有类型Any(包括值类型和引⽤类型)的⼦类型,它不在有⼦类型,它也没有实例,实际上为了⼀个⽅法抛出异常,通常会设置⼀个默认返回类型。
Nil代表⼀个List空类型,等同List[Nothing]。
None是Option的一个实例,代表空结果集的返回。
Unit类型是什么?
没有任何意义的值的类型,类似与void,anyval的子类,仅有一个实例对象
Yield是什么?scala> for (i <- 1 to 5) yield i * 2产生结果是?
用于循环迭代中生成新值,vector(2,4,6,8,10)
元组是什么,如何创建和使用
元组就是元素的组合,val tuple1 = (1, 2, 3, “heiheihei”),类型无所谓
Scala中的模式匹配和Java的匹配模式的区别
scala的模式匹配包括了一系列的备选项,每个替代项以关键字大小写为单位,每个替代方案包括一个模式或多个表达式,如果匹配将会进行计算,箭头符号=>将模式与表达式分离。
而Java的匹配模式是switch
case匹配方式,它内部匹配的类型有局限性,并且需要用Break跳出匹配模式,而Scala中只会匹配其中一个结果,同时匹配类型居多,如String、Array、List、Class等
Scala中的to和until 有什么区别
to左闭右闭,until左闭右开
什么是高阶函数?
高阶函数指能接受或者返回其他函数的函数,scala中的filter map flatMap函数都能接受其他函数作为参数
手写Scala单例模式
object SingletonOps {
def main(args: Array[String]): Unit = {
val singleton1 = Singleton.getInstance
val singleton2 = Singleton.getInstance
println(singleton1 == singleton2)
singleton1.index = 5
println("singleton1.index: " + singleton1.index)
println("singleton2.index: " + singleton2.index)
}
}
object Singleton {
private val singleton = Singleton;
def getInstance = singleton
var index = 1
}