目标:了解常见的编程语言范式及优缺点
编程范式:Programming paradigm
主流的三种编程范式
面向过程编程范式 / 结构化编程
设计思想:将实现过程拆解为数据结构和算法,数据结构用于存储数据,算法用于处理数据,依次根据需求调用来实现
代表:C语言
优点
缺点
栗子:老王要开车
c.getKey
c.driver
如果a也想开车,必须重新构建一个a这个类,重新定义getkey和driver方法
面向对象编程范式
设计思想:将所有逻辑拆解为实体和关系,核心特点是封装、继承和多态
代表:Java、C++
优点
- 面向对象思想,更容易理解和抽象
- 代码更容易重用
- 开放性更好,也易维护
缺点
栗子:老王要开车
class Person(name,age,gender,getKey(),driver())
class C extends Person
c = new C
c.getKey
c.driver
如果a也想开车
class A extends Person
a = new A
a.getKey
a.driver
函数式编程范式
- 设计思想:将所有操作全部基于数据和函数实现,==函数作为一等公民==,开发者不需要关心底层
- 优点
- 高度抽象,代码简洁高效
- 不可变设计,易于并发编程
- 声明式代码表达,易于理解
- 缺点
- 性能相对比其他两种都较差
- 栗子:老王要开车
```
c.driver()
a.driver()
```
小结
Scala的官网:https://www.scala-lang.org/
Scala combines object-oriented and functional programming in one concise, high-level language. Scala's static types help avoid bugs in complex applications, and its JVM and JavaScript runtimes let you build high-performance systems with easy access to huge ecosystems of libraries.
Scala是一门集成了面向对象编程和面向函数式编程的高级语言
Scala通过静态类型避免复杂程序中的bug
Scala基于JVM可以实现简单的访问高性能的JVM生态圈
Scala的定义
Scala的特点
基于JVM:可移植性非常好
支持面向对象:保留了面向对象的优点,兼容面向对象开发
支持函数式编程:支持函数式编程的特点:函数是一等公民、惰性赋值、高阶函数、不可变数据等
Scala的应用场景
小结
Windows中部署Scala SDK
step2:配置环境变量
step3:开启CMD,测试
Linux中部署Scala SDK
step1:上传解压安装
tar -zxvf scala-2.11.12.tgz -C /export/server/
step2:修改环境变量
vim /etc/profile
#SCALA_HOME
export SCALA_HOME=/export/server/scala-2.11.12
export PATH=$PATH:$SCALA_HOME/bin
source /etc/profile
step3:进入scala命令行测试
进入命令行
scala
打印输出
println("Hello,scala")
退出命令行
:quit
IDEA中安装Scala插件的两种方式
IDEA中在线安装Scala插件
IDEA中创建Scala工程
方式二:Maven工程:自动管理依赖
变量的定义语法及测试
功能:定义一个值可变的变量
语法
var 变量名称:数据类型 = 值
Scala中大多数场景下可以自动推断类型
常量的定义语法及测试
语法
val 常量名称:数据类型 = 值
初始值
语法
var 变量名称:数据类型 = _
注意
只能用于变量
必须指定类型,不能自动推断类型
惰性赋值
功能:构建一个常量时不直接赋值,只构建常量对象,当用到数据内容时,再真正赋值
设计:避免值初始化以后,如果不被调用,占用内存,通过lazy使用时再进行初始化分配
语法
lazy val 常量名称:数据类型 = 值
特点及注意事项
Scala代码不以分号结尾
Scala中大多数场景可以自动推断类型
Scala中推荐使用常量,不推荐使用变量:val
scala中名称在前、类型在后 中间以:分割
大多数场合写可以省去类型不写,编译器可以自动推导
初始值不能用于常量,只能用于变量,并且必须指定数据类型
惰性赋值只能用于常量,不能用于变量
Scala中的数据类型
基本类型:Int、Double……
引用类型:String、集合、对象……
Scala中的数据类型运算
运算符:+、-、*、/ 、% ……
本质:所有数据类型都是对象,所有数据类型的运算符都是这个对象的方法
Scala中数据类型的层次结构
基本类型大体与Java中是一致的
Unit类似于Java中的void,没有任何实质性的意义,一般用于作为标识函数无返回值
Null类型是所有引用类型的子类
Nothing是所有类型的子类,一般用于作为函数返回值,用于明确的标识没有返回值
def name(args):Nothing= {
方法体
Nothing
}
父类:Any
子类:Nothing
字符串定义
双引号定义
三引号定义:用于比较长的字符串定义,可读性比较强
scala> val s2 = """
| select xxxxx
| from xxxx
| where xxxx
| group by xxx
| having xxxx
| order by xxxx
| limit xxx
| """
字符串截取substring
scala> s1.substring(2)
res9: String = cast
字符串替换replaceAll
scala> s3.replaceAll(" ","-")
字符串拼接
scala> s3.+(s1)
res18: String = I likeitcast
插值表达式的使用
功能:用于字符串拼接,可以在字符串中插入变量或者表达式
语法
s"${变量 | 表达式}"
块表达式
功能:用{}包裹多行代码的表达式,scala中使用最后一行作为表达式的返回值,如果表达式只有一行代码,{}可以省略
语法
{
第一行代码
第二行代码
……
表达式返回值
}
if判断
功能:用于实现代码中的判断分支逻辑
语法
if(表达式1){
表达式1为true
}else if(表达式2){
表达式2为true
}else if(表达式N){
表达式N为true
}else{
都不满足
}
Scala中for循环的语法
for(i <- 集合/数值范围){
循环逻辑
}
Scala中构建数值范围表达式
scala> 1 to 10 或 1.to(10)
res30: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> 1.until(10)
res32: scala.collection.immutable.Range = Range(1, 2, 3, 4, 5, 6, 7, 8, 9)
for循环栗子
scala> for(i <- 1 to 10) {
println(i)}
守卫条件
功能:循环过程中实现数据过滤,增加循环条件,符合条件才会执行循环逻辑
优点:不是每次循环都会执行循环体,只有符合条件才执行循环体
语法
for(x <- 集合/数值范围 守卫条件表达式){
循环逻辑
}
栗子
scala> for(i <- 1 to 10 if i%2 == 0) {
println(i)}
2
4
6
8
10
推导式yield
功能:在for循环后面加上表达式,针对循环的结果进行表达式的计算 ,计算结果组成一个新的集合
关键字:yield
语法
for(i <- 集合/数值范围) yield {
循环表达式
//计算表达式
}
- 栗子
```scala
scala> for(i <- 1 to 10) yield i*2
res40: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
语法
while(表达式){
符合条件的循环逻辑
}
do {
循环逻辑
} while( 表达式 );
Scala中的continue与break
栗子
实现break
import scala.util.control.Breaks._
breakable{
for(i <- 1 to 10) {
if(i >= 5) break()
else println(i)
}
}
实现continue
import scala.util.control.Breaks._
for(i <- 1 to 10){
breakable{
if(i == 5) break()
else println(i)
}
}
方法与函数的区别
public 返回值 方法名(参数){
方法体
}
方法:由方法名、参数、方法体构成,一般指的是类中定义的函数即为方法
函数:由函数名、参数、函数体构成,一般指的是可以独立构建的称为函数
Scala中定义方法的语法
def funcName(args1:Type1,args2:Type2……):ResultType = {
//方法体
}
栗子:定义一个方法,实现传递两个Int参数,返回两个数值之和
scala> def m1(a:Int,b:Int):Int = {
| a + b
| }
规则
方法定义的关键字为def
如果方法体只有一行,{}可以省略
没有return关键字,使用方法体的最后一行【值或者表达式】作为返回值
大多数情况下返回值类型也可以自动推断,可以不写,递归方法除外
小结
方法与函数的区别?
Scala中定义方法的语法?
def 方法名(参数):返回值类型 = {
方法体
}
方法定义的规则?
默认参数的方法定义
功能:在方法定义时,给定参数的默认值
语法
def funName(args1:Type1 = Value1,args2:Type2 = Value2 ……):ResultType = {
//方法体
}
栗子:定义一个方法,实现传递两个Int参数,返回两个数值之和
def m5(a:Int = 0,b:Int = 2) = a + b
默认参数的方法调用
scala> def m5(a:Int = 0,b:Int = 2) = a + b
m5: (a: Int, b: Int)Int
scala> m5(1,1)
res15: Int = 2
scala> m5(1,6) --指定所有参数
res16: Int = 7
scala> m5() --使用两个参数的默认值
res17: Int = 2
scala> m5(1) --给第一个参数赋值,第二个参数使用默认值
res18: Int = 3
scala> m5(a=1)
res19: Int = 3
scala> m5(b=1)
res20: Int = 1
scala> m5(b=4,a=3) --指定参数赋值
res21: Int = 7
变长参数的方法定义
功能:用于定义方法时传递不定个数的参数
语法
def funName(args1:Type1 *):ResultType = {
//方法体
}
本质:将所有参数放入一个数组中,*表示多个
栗子:定义一个方法,实现传递1个或者多个Int参数,返回所有参数之和
scala> def m6(x:Int *) = x.sum
m6: (x: Int*)Int
scala> m6(1)
res22: Int = 1
scala> m6(1,2)
res23: Int = 3
scala> m6(1,2,4)
res24: Int = 7
小结
目标:掌握Scala中方法的三种调用形式
路径:Scala中的方法如何实现调用?
实施
后缀调用法:最常见的最常用的方式
语法
对象.方法(参数)
栗子
scala> 1.to(10)
res25: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> 1.until(10)
res26: scala.collection.immutable.Range = Range(1, 2, 3, 4, 5, 6, 7, 8, 9)
中缀调用法/中缀表达式
语法
对象 方法 参数
栗子
scala> 1 to 10
res27: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> 1 until 10
res28: scala.collection.immutable.Range = Range(1, 2, 3, 4, 5, 6, 7, 8, 9)
花括号调用法
语法
对象.方法{参数}
栗子
scala> m7{1}
res30: Int = 6
注意:只能用于单个参数的方法调用
scala> def m8(a:Int,b:Int) = a + b
m8: (a: Int, b: Int)Int
scala> m8(1,2)
res31: Int = 3
scala> m8{
1,2}
<console>:1: error: ';' expected but ',' found.
m8{
1,2}
小结
目标:掌握Scala中函数的定义及其语法规则
路径:函数如何定义?函数的本质是什么?
实施
函数的定义及语法
语法
(参数) => {
//函数体
}
栗子1:定义一个函数,传递两个Int参数,返回两个参数的和
scala> (x:Int,y:Int) => {
x + y }
res32: (Int, Int) => Int = <function2>
scala> val str1 = "itcast"
str1: String = itcast
栗子2:定义一个函数,传递1个Int参数,返回参数值+5
scala> (x:Int) => x + 5
res33: Int => Int = <function1>
函数的使用规则
函数的本质
Scala中函数的本质就是对象,每个函数就是一个FunctionN类的实例,N表示参数个数
调用函数的本质是调用了这个对象的方法实现的
所以要定义、调用函数,必须指定参数列表,不然只是定义或者调用了这个对象,而不是这个对象的方法
scala> def m9() = 1 + 2
m9: ()Int
scala> m9 --调用方法
res35: Int = 3
scala> m9() --调用方法
res36: Int = 3
scala> () => 1 + 2
res37: () => Int = <function0>
scala> res37() --调用函数对象的方法
res38: Int = 3
scala> res37 --调用函数的对象
res39: () => Int = <function0>
小结
函数的定义及语法?
(参数) => {
函数体
}
函数的使用规则?
函数的本质?
目标:掌握Scala中的函数的分类
路径:Scala中的函数分为几类?什么是匿名函数?什么是值函数?什么是高阶函数?
实施
Scala中函数的分类
匿名函数的功能及定义
定义:定义一个函数,但不指定函数的名称
应用:一般用于作为高阶函数的参数
栗子
(x:Int,y:Int) => x + y
值函数的功能及定义
定义:定义一个函数,将这个函数赋值给一个变量或者常量,用于构建函数名称,调用函数
应用:一般用于定义函数名称
栗子
scala> val f1 = (x:Int,y:Int) => x + y
f1: (Int, Int) => Int = <function2>
scala> f1(1,2)
res43: Int = 3
高阶函数的功能及定义
定义:如果使用函数值作为参数,或者返回值为函数值的“函数”和“方法”,均称之为“高阶函数”。
应用:用于更加灵活的实现数据的处理
栗子:定义一个函数,用于根据需求实现两个数字的加、减、乘、除
传统写法
def f2(x:Int,y:Int,flag:Int){
if(flag == 1){
x + y
}else if (flag == 2){
x - y
}
……
}
高阶函数
def f3(p:(Int,Int) => Int):Int = {
p(4,2)
}
val fa = (x:Int,y:Int) => x+y
val fb = (x:Int,y:Int) => x-y
val fc = (x:Int,y:Int) => x*y
val fd = (x:Int,y:Int) => x/y
f3(fa) --使用值函数作为参数
|
f3((x:Int,y:Int) => x+y) --使用匿名函数作为参数
小结
匿名函数的功能及定义?
目标:掌握如何将方法转换为一个函数
路径:如何将定义的一个方法转换为一个函数,当做函数来使用呢?
实施
step1:创建两个方法
高阶函数m1
scala> def m1(f:(Int,Int) => Int) : Int = {
| f(4,2)
| }
m1: (f: (Int, Int) => Int)Int
普通方法m2
scala> def m2(a:Int,b:Int) = a + b
m2: (a: Int, b: Int)Int
step2:将m2由方法转换为函数
scala> val f1 = m2 _
f1: (Int, Int) => Int = <function2>
step3:高阶函数中调用f1
scala> m1(f1)
res58: Int = 6
scala> m1(m2) --Scala底层实现了隐式转换:自动转换类型
res50: Int = 6
小结
如何将定义的一个方法转换为一个函数,当做函数来使用呢?
val 函数名 = 方法名 _
目标:了解Scala中数组与集合的分类以及应用场景
路径
实施
Scala中的集合和数组的分类
不可变:immutable
推荐使用不可变
可变数组和可变集合
可变:mutable,指的是数组或集合中的元素的值可变或者长度可变
库
scala.collection.mutable._
scala.collection.mutable.ArrayBuffer
集合
scala.collection.mutable.ListBuffer
scala.collection.mutable.Map
scala.collection.mutable.Set
不可变数组和不可变集合
库
scala.collection.immutable._
数组
scala.Array
集合
scala.collection.immutable.List
scala.collection.immutable.Map
scala.collection.immutable.Set
应用场景
如果业务中需要使用可变类型,一般最终也转换为不可变类型
小结
Scala中的集合和数组的分类?
一般指的是元素的值或者长度可变
一般指的是元素的值或者长度不可变
可变数组和可变集合?
不可变数组和不可变集合?
目标:掌握Scala中可变数组ArrayBuffer与不可变数组Array的使用
路径:ArrayBuffer与Array的区别是什么?如何使用Array和ArrayBuffer?
实施
ArrayBuffer与Array的区别
Array的定义、赋值及取值
定义
//用于指定数组长度,没有指定初始值,必须加new
scala> val a1 = new Array[Int](5)
a1: Array[Int] = Array(0, 0, 0, 0, 0)
//指定了初始值可以不加new
scala> val a2 = Array(1,2,3,4,5)
a2: Array[Int] = Array(1, 2, 3, 4, 5)
赋值
scala> a1(0) = 10
scala> a1
res1: Array[Int] = Array(10, 0, 0, 0, 0)
Scala中引用下标使用圆括号
下标从0开始
取值
scala> a1(0)
res2: Int = 10
scala> println(a1(0))
10
scala> for(i <- a1 ) println(i)
10
0
0
0
0
scala> for(i <- a2 ) println(i)
1
2
3
4
5
scala> for(i <- 0.to(4) ) println(i)
0
1
2
3
4
scala> for(i <- 0.to(4) ) println(a2(i))
1
2
3
4
5
scala> for(i <- 0.to(a2.length - 1) ) println(a2(i))
1
2
3
4
5
scala> for(i <- a2.reverse ) println(i)
5
4
3
2
1
scala> for(i <- (a2.length - 1).to(0) ) println(a2(i))
scala> for(i <- (a2.length - 1).to(0,-1) ) println(a2(i))
5
4
3
2
1
scala> for(i <- (a2.length - 1).to(0,-2) ) println(a2(i))
5
3
1
ArrayBuffer的定义、赋值及取值
定义
scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer
scala> val ab1 = new ArrayBuffer[Int]()
ab1: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()
scala> val ab2 = ArrayBuffer(1,2,3)
ab2: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)
增加:+=、append
scala> ab1 += 10
res13: ab1.type = ArrayBuffer(10)
scala> ab1 += 9
res14: ab1.type = ArrayBuffer(10, 9)
scala> ab1 += 7
res15: ab1.type = ArrayBuffer(10, 9, 7)
scala> ab1.append(8)
scala> ab1
res17: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(10, 9, 7, 8)
scala> a1
res18: Array[Int] = Array(10, 0, 0, 0, 0)
赋值
scala> ab1(1) = 8
scala> ab1
res21: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(10, 8, 7, 8)
取值
scala> for(x <- ab1) println(x)
10
8
7
8
删除:-= 、remove
//按照值进行剔除
scala> ab1 -= 8
res23: ab1.type = ArrayBuffer(10, 7, 8)
//按照下标剔除
scala> ab1.remove(1)
res24: Int = 7
scala> ab1
res25: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(10, 8)
数组中的常用操作
排序:sorted
scala> ab2.sorted
res31: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 3, 5, 7, 10)
反转:reverse
scala> ab2.sorted.reverse
res32: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(10, 7, 5, 3, 3, 2, 1)
求和:sum
scala> ab2.sum
res33: Int = 31
最大:max
scala> ab2.max
res34: Int = 10
最小:min
scala> ab2.min
res35: Int = 1
转换为字符串:mkString
scala> ab2.mkString
def mkString(sep: String): String
def mkString: String def mkString(start: String,sep: String,end: String): String
scala> ab2.mkString
res38: String = 12373510
scala> ab2.mkString("-")
res39: String = 1-2-3-7-3-5-10
scala> ab2.mkString(",")
res40: String = 1,2,3,7,3,5,10
scala> ab2.mkString("<",",",">")
res41: String = <1,2,3,7,3,5,10>
scala> ab2.mkString("<","-",">")
res42: String = <1-2-3-7-3-5-10>
小结
ArrayBuffer与Array的区别?
Array的定义、赋值及取值?
new Array[类型](长度)
Array(给定初始值)
array(index) = value
for(i <- array)
ArrayBuffer的定义、赋值及取值?
new ArrayBuffer[类型]()
ArrayBuffer(初始值)
array +=/append
array -=/remove
array(index) = value
for(i <- array)
数组中的常用操作?
目标:掌握Scala中List集合与ListBuffer的区别以及使用
路径:List与ListBuffer的区别是什么?List与ListBuffer如何使用?
实施
有序可重复的集合
List与ListBuffer的区别
List的定义、赋值及取值
定义
scala> val list1 = List(1,2,3,4,5,6,6,1,2)
list1: List[Int] = List(1, 2, 3, 4, 5, 6, 6, 1, 2)
scala> list1(0) = 10
<console>:14: error: value update is not a member of List[Int]
list1(0) = 10
^
值不可改变
取值
scala> list1(0)
res44: Int = 1
scala> for(i <- list1) println(i)
1
2
3
4
5
6
6
1
2
ListBuffer的定义、赋值及取值
定义
scala> val listb1 = new ListBuffer[Int]()
listb1: scala.collection.mutable.ListBuffer[Int] = ListBuffer()
scala> val listb2 = ListBuffer(1,2,3,4,3,2,1)
listb2: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 4, 3, 2, 1)
添加:+=、append
scala> listb1 += 1
res52: listb1.type = ListBuffer(10, 9, 8, 1)
scala> listb1.append(3)
scala> listb1
res57: scala.collection.mutable.ListBuffer[Int] = ListBuffer(10, 2, 8, 1, 3)
赋值
scala> listb1(1) = 2
scala> listb1
res55: scala.collection.mutable.ListBuffer[Int] = ListBuffer(10, 2, 8, 1)
删除:-=、remove
scala> listb1 -= 10
res58: listb1.type = ListBuffer(2, 8, 1, 3)
scala> listb1.remove(0)
res59: Int = 2
scala> listb1
res60: scala.collection.mutable.ListBuffer[Int] = ListBuffer(8, 1, 3)
取值
scala> listb1(0)
res61: Int = 8
scala> for(x <- listb1) println(x)
8
1
3
小结
List与ListBuffer的区别?
List的定义及取值?
val list = List(初始值)
ListBuffer的定义、赋值及取值?
val listb = new ListBuffer[类型]()
val listb = ListBuffer(初始值)
目标:掌握List与ListBuffer的常用操作
路径
实施
List集合常用操作
取第1个元素:head
scala> list1.head
res64: Int = 1
取除了第一个元素以外的元素:tail
scala> list1.tail
res65: List[Int] = List(2, 3, 4, 5, 6, 6, 1, 2)
取前N个元素:take
scala> list1.take(3)
res66: List[Int] = List(1, 2, 3)
取除了前N个元素以外的所有元素:drop
scala> list1.drop(3)
res67: List[Int] = List(4, 5, 6, 6, 1, 2)
定义一个空list集合:Nil
scala> val list2 = Nil
list2: scala.collection.immutable.Nil.type = List()
集合头部添加元素返回新的集合:+:、::
scala> list1.+:(10)
res69: List[Int] = List(10, 1, 2, 3, 4, 5, 6, 6, 1, 2)
scala> list1
res70: List[Int] = List(1, 2, 3, 4, 5, 6, 6, 1, 2)
scala> 9::list1
res71: List[Int] = List(9, 1, 2, 3, 4, 5, 6, 6, 1, 2)
集合尾部添加元素返回新的集合::+
scala> list1.:+(10)
res72: List[Int] = List(1, 2, 3, 4, 5, 6, 6, 1, 2, 10)
拼接两个集合的元素返回新的集合:++、:::
scala> list3:::list4
res73: List[Int] = List(1, 2, 3, 4, 3, 4, 5, 6)
scala> list4:::list3
res74: List[Int] = List(3, 4, 5, 6, 1, 2, 3, 4)
scala> list3 ++ list4
res75: List[Int] = List(1, 2, 3, 4, 3, 4, 5, 6)
scala> list4 ++ list3
res76: List[Int] = List(3, 4, 5, 6, 1, 2, 3, 4)
扁平化操作:将两层集合转换为一层集合:flatten
scala> val list5 = List(List(1,2),List(3,4),List(5,6))
list5: List[List[Int]] = List(List(1, 2), List(3, 4), List(5, 6))
scala> for(x <- list5) println(x)
List(1, 2)
List(3, 4)
List(5, 6)
scala> list5.flat
flatMap flatten
scala> list5.flatten
res78: List[Int] = List(1, 2, 3, 4, 5, 6)
拉链操作:zip、zipWithIndex
scala> val list6 = List(1,2,3,4)
list6: List[Int] = List(1, 2, 3, 4)
scala> val list7 = List("a","b","c","d")
list7: List[String] = List(a, b, c, d)
scala> list6.zip(list7)
res79: List[(Int, String)] = List((1,a), (2,b), (3,c), (4,d))
scala> list7.zipWithIndex
res80: List[(String, Int)] = List((a,0), (b,1), (c,2), (d,3))
拉开操作:unzip
scala> val list8 = list6.zip(list7)
list8: List[(Int, String)] = List((1,a), (2,b), (3,c), (4,d))
scala> list8.unzip
res81: (List[Int], List[String]) = (List(1, 2, 3, 4),List(a, b, c, d))
scala> val list9 = list8.unzip
list9: (List[Int], List[String]) = (List(1, 2, 3, 4),List(a, b, c, d))
scala> list9._1
res82: List[Int] = List(1, 2, 3, 4)
scala> list9._2
res83: List[String] = List(a, b, c, d)
并集:union
scala> list3.union(list4)
res86: List[Int] = List(1, 2, 3, 4, 3, 4, 5, 6)
交集:intersect
scala> list3.intersect(list4)
res87: List[Int] = List(3, 4)
差集:diff
scala> list3.diff(list4)
res88: List[Int] = List(1, 2)
scala> list4.diff(list3)
res89: List[Int] = List(5, 6)
ListBuffer集合常用操作
scala> listb1.to
to toBuffer toIterable toList toParArray toSet toString toVector
toArray toIndexedSeq toIterator toMap toSeq toStream toTraversable
转换为List:toList
scala> listb1.toList
res91: List[Int] = List(8, 1, 3)
转换为Array:toArray
scala> listb1.toArray
res92: Array[Int] = Array(8, 1, 3)
小结
目标:掌握Scala中Set集合的使用
路径:可变的Set与不可变Set的区别?Set集合的使用?
实施
Set集合的特点
可变Set集合与不可变Set的区别
不可变Set集合的定义与读取
定义
scala> val set1 = Set(1,2,3,4,4,2,1,3)
set1: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4)
取值
scala> for(i <- set1 ) println(i)
1
2
3
4
获取集合长度:size
scala> set1.size
res100: Int = 4
可变Set集合的定义、赋值与读取
定义
scala> import scala.collection.mutable.Set
import scala.collection.mutable.Set
scala> val set2 = Set(1,2,3,4,4,2,1,3)
set2: scala.collection.mutable.Set[Int] = Set(1, 2, 3, 4)
添加:+=
scala> set2 += 4
res102: set2.type = Set(1, 5, 2, 3, 4)
删除:-=
scala> set2 -= 2
res103: set2.type = Set(1, 5, 3, 4)
读取
scala> for(i <- set2) println(i)
1
5
3
4
小结
Set集合的特点?
可变Set集合与不可变Set的区别?
不可变Set集合的定义与读取?
val set = Set(初始值)
可变Set集合的定义、赋值与读取?
//先导包
val set = Set(初始值)
目标:掌握Scala中Map集合的使用
路径:可变Map与不可变Map的区别?Map集合的使用?
实施
Map集合的特点
可变Map与不可变Map的区别
不可变Map集合的定义、读取
定义
scala> val map1 = Map("name" -> "laoda","age" -> "20","gender"->"male")
map1: scala.collection.immutable.Map[String,String] = Map(name -> laoda, age -> 20, gender -> male)
scala> val map2 = Map(("name","laoer"),("age","22"),("gender","female"))
map2: scala.collection.immutable.Map[String,String] = Map(name -> laoer, age -> 22, gender -> female)
读取
方式一:直接根据Key读取
scala> map1("name")
res105: String = laoda
scala> map1("name1")
java.util.NoSuchElementException: key not found: name1
at scala.collection.MapLike$class.default(MapLike.scala:228)
at scala.collection.AbstractMap.default(Map.scala:59)
at scala.collection.MapLike$class.apply(MapLike.scala:141)
at scala.collection.AbstractMap.apply(Map.scala:59)
... 32 elided
方式二:使用get方法
scala> map1.get
def get(key: String): Option[String]
scala> map1.get("name")
res107: Option[String] = Some(laoda)
scala> map1.get("name").get
res108: String = laoda
scala> map1.get("name1")
res109: Option[String] = None
方式三:使用getOrElse方法
scala> map1.getOrElse("name1","null")
res112: String = null
scala> map1.getOrElse("name","null")
res113: String = laoda
方式四:循环挨个取值
scala> for(x <- map1) println(x)
(name,laoda)
(age,20)
(gender,male)
scala> for((key,value) <- map1) println(key+"\t"+value)
name laoda
age 20
gender male
可变Map集合的定义、添加、读取
定义
scala> import scala.collection.mutable.Map
import scala.collection.mutable.Map
scala> val map3 = Map(("name","laoer"),("age","22"),("gender","female"))
map3: scala.collection.mutable.Map[String,String] = Map(age -> 22, name -> laoer, gender -> female)
添加:+=
scala> map3 += "addr" -> "shanghai"
res116: map3.type = Map(addr -> shanghai, age -> 22, name -> laoer, gender -> female)
更新:=
scala> map3("addr") = "beijing"
scala> map3
res120: scala.collection.mutable.Map[String,String] = Map(addr -> beijing, age -> 22, gender -> female)
删除:remove
scala> map3.remove("name")
res117: Option[String] = Some(laoer)
scala> map3
res118: scala.collection.mutable.Map[String,String] = Map(addr -> shanghai, age -> 22, gender -> female)
获取Key:keys
scala> map3.keys
res121: Iterable[String] = Set(addr, age, gender)
获取Value:values
scala> map3.values
res122: Iterable[String] = HashMap(beijing, 22, female)
遍历
for(x <- map3) println(x)
for((key,value)<- map3) println(key+"\t"+value)
for(key <- map3.keys) println(map3(key))
小结
Map集合的特点?
可变Map与不可变Map的区别?
不可变Map集合的定义、读取?
val map = Map(key1->value1,key2->value2……)
可变Map集合的定义、添加、读取?
import scala.collection.mutable.Map
val map = Map(key1->value1,key2->value2……)
目标:掌握Scala中元组的使用
路径:什么是元组?元组的使用方式和场景?
实施
元组的功能和特点
元组的语法
val/var tupleName = (元素1,元素2,元素3,元素4……)
val/var tupleName = TupleN(元素1,元素2,元素3,元素4……元素N)
举例
scala> val tuple1 = (1,2,"itcast",14.9,true)
tuple1: (Int, Int, String, Double, Boolean) = (1,2,itcast,14.9,true)
scala> val tuple2 = new Tuple3(1,2,"heima")
tuple2: (Int, Int, String) = (1,2,heima)
特殊:二元组就是KeyValue对
方法:swap:二元组特有的方法
元组最多只能有22个元素
元组的取值
通过tuple._N来引用元组中的元素(N从1开始)
举例
scala> tuple1._1
res126: Int = 1
scala> tuple1._2
res127: Int = 2
scala> tuple1._3
res128: String = itcast
小结
元组的功能和特点?
元组的定义?
val tuple = (e1,e2,e3……)
val tuple = new TupleN(N个元素)
元组的取值?
目标:了解Scala中迭代器的使用
路径:
实施
scala针对每一类集合都提供了一个迭代器(iterator)用来迭代访问集合
迭代器的两个基本方法
举例
scala> val array = Array(1,2,3,4,5)
array: Array[Int] = Array(1, 2, 3, 4, 5)
scala> val itera = array.iterator
itera: Iterator[Int] = non-empty iterator
scala> while(itera.hasNext) println(itera.next)
1
2
3
4
5
小结
目标:掌握集合高阶函数map的功能及用法
路径
实施
map函数的语法
final def map[B](f: (A) ⇒ B): List[B]
//map函数只有1个参数,这个参数是一个函数类型
f: (A) ⇒ B:f就是参数函数
//f有1个参数:A:代表集合中的每个元素
//f的返回值:B:B是A处理以后的返回值
List[A].map = List[B]
A1 -> B1
A2 -> B2
……
map函数的功能
map函数用于将集合中的每个元素调用参数函数进行处理,并将每个元素处理的返回值放入一个新的集合中
集合中元素一对一的处理
处理逻辑:由传递的参数函数来决定了
f:A => B
val f = (A) => {
//处理A逻辑
B
}
一般用于集合数据处理,这是最常用的处理函数
栗子
需求一:对以下集合进行处理,返回集合中每个元素的平方
val list1 = List(1,2,3,4,5,6,7,8,9,10)
scala> list1.map((numb) => {
| println(numb)
| numb*numb
| })
1
2
3
4
5
6
7
8
9
10
res0: List[Int] = List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100)
scala> list1.map(numb => numb*numb)
res1: List[Int] = List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100)
需求二:对以下集合进行处理,返回集合中每个字符串并在字符串的后面拼接字符串长度
val list2 = List("hadoop","","hive","hue"," ")
scala> list2.map(word => word+"-"+word.length)
res3: List[String] = List(hadoop-6, -0, hive-4, hue-3, " -1")
小结
map函数的功能与应用场景?
map函数的语法?
list.map(A=>B):List[B]
目标:掌握集合高阶函数foreach的功能及用法
路径
实施
foreach函数的语法
final def foreach(f: (A) ⇒ Unit): Unit
//foreach有1个参数,是一个函数f
//f这个函数有1个参数:A:代表集合中的每个元素
//f这个函数没有返回值
foreach函数的功能与应用场景
用于将集合中的每个元素进行处理,但是没有返回值
一般用于将集合的数据进行输出或者保存:将数据结果打印或者写入外部文件系统
栗子
需求一:对以下集合进行处理,输出集合中的每个元素
val list1 = List(1,2,3,4,5,6,7,8,9,10)
scala> list1.foreach(i => println(i))
1
2
3
4
5
6
7
8
9
10
scala> list1.foreach(println(_))
1
2
3
4
5
6
7
8
9
10
scala> list1.foreach(println)
1
2
3
4
5
6
7
8
9
10
需求二:对以下集合进行处理,输出集合中每个字符串并在字符串的后面拼接字符串长度
val list2 = List("hadoop","","hive","hue"," ")
scala> val list2 = List("hadoop","","hive","hue"," ")
list2: List[String] = List(hadoop, "", hive, hue, " ")
scala> list2.foreach(word => println(word+"\t"+word.length))
hadoop 6
0
hive 4
hue 3
1
小结
foreach函数的功能与应用场景?
功能:对集合中的每个元素进行处理,但是没有返回值
foreach函数的语法?
list.foreach(f:A => Unit):Unit
目标:掌握集合高阶函数flatMap的功能及用法
路径
实施
flatMap函数的语法
final def flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): List[B]
//flatMap有1个参数f,是一个函数
//f这个函数有1个参数:A:集合中的每个元素
//f这个函数有返回值: GenTraversableOnce[B],对每个A处理以后返回的结果,是一个集合,集合中有多个元素B
//flatMap返回值是:List[B]:将每个A返回的集合进行合并
基本原理:f:调用每个元素进行map处理,map返回值是List,每个元素放回一个集合,最终每个元素处理的结果:List[List[B]]
flatMap会将这个List[List[B]] 变成List[B]
flatMap函数的功能
栗子
需求一:对以下集合进行处理,将所有数字合并到一个集合中
val m1 = Map("key1"->"1,2,3","key2"->"4,5,6","key3"->"7,8,9")
scala> m1.values
res11: Iterable[String] = MapLike(1,2,3, 4,5,6, 7,8,9)
scala> m1.values.foreach(println)
1,2,3
4,5,6
7,8,9
scala> m1.values.flatMap(x => x.split(",")).foreach(println)
1
2
3
4
5
6
7
8
9
```
需求二:对以下集合进行处理,将所有单词放入一个集合中
val list5 = List("hadoop spark"," spark","hive hbase ","hue hue spark"," hue ")
scala> list5.flatMap(line => line.split(" "))
res14: List[String] = List(hadoop, spark, "", spark, hive, hbase, hue, hue, spark, "", hue)
scala> list5.flatMap(line => line.trim.split(" "))
res15: List[String] = List(hadoop, spark, spark, hive, hbase, hue, hue, spark, hue)
小结
flatMap函数的功能?
flatMap函数的语法?
def flatMap(A => List[B]):List[B]
目标:掌握集合高阶函数groupBy的功能及用法
路径
实施
groupBy函数的语法
def groupBy[K](f: (A) ⇒ K): Map[K, List[A]]
//groupBy传递一个参数f:函数参数
//f有一个参数:A:每个元素
5
(key,value)
(tup1,tup2,tupe3)
//f有一个返回值:K:按照谁分组
//groupBy返回值:Map[K, List[A]],每个KV代表一组
K:分组的那个组
V:List[A],符合K的所有A的集合
groupBy函数的功能
栗子
需求一:对以下集合进行处理,按照奇偶数进行分组
val list3 = List(2,4,6,8,9,7,5,3,1)
scala> list3.groupBy( x => x%2==0).foreach(println)
(false,List(9, 7, 5, 3, 1))
(true,List(2, 4, 6, 8))
需求二:对以下集合进行处理,按照地区进行分组
val m2 = Map(1->"shanghai",2->"beijing",3->"jiangsu",4->"anhui",5->"beijing",6->"anhui",7->"anhui",8->"shanghai",9->"beijing",10->"beijing")
scala> m2.groupBy(tuple => tuple._2).foreach(println)
(jiangsu,Map(3 -> jiangsu))
(shanghai,Map(1 -> shanghai, 8 -> shanghai))
(anhui,Map(6 -> anhui, 7 -> anhui, 4 -> anhui))
(beijing,Map(5 -> beijing, 10 -> beijing, 9 -> beijing, 2 -> beijing))
小结
groupBy函数的功能?
groupBy函数的语法?
def groupBy(A => K):Map[(K,List[A])]
目标:掌握集合高阶函数filter和filterNot的功能及用法
路径
实施
filter函数的语法
def filter(p: (A) ⇒ Boolean): List[A]
//filter函数传递1个参数:p:函数
//p的参数:A:每个元素
//p的返回值:Boolean,一般是表达式的结果
//filter的返回值:List[A] :所有符合表达式的元素的集合
filter函数的功能
filterNot函数的语法
def filterNot(p: (A) ⇒ Boolean): List[A]
filterNot函数的功能
栗子
需求一:对以下集合进行处理,返回集合中所有的偶数
val list1 = List(1,2,3,4,5,6,7,8,9,10)
scala> list1.filter( x => x % 2 == 0)
res20: List[Int] = List(2, 4, 6, 8, 10)
scala> list1.filterNot(x => x % 2 != 0)
res21: List[Int] = List(2, 4, 6, 8, 10)
需求二:对以下集合进行处理,过滤掉所有不是单词的元素
val list2 = List("hadoop","","hive","hue"," ")
scala> list2.filter(word => word.trim.length > 0)
res22: List[String] = List(hadoop, hive, hue)
scala> list2.filter(_.trim.length > 0)
res23: List[String] = List(hadoop, hive, hue)
小结
filter函数的功能?
filter函数的语法?
def filter(A => 条件表达式):List[A]
filterNot函数的功能?
filterNot函数的语法?
def filterNot(A => 条件表达式):List[A]
目标:掌握集合高阶函数sortWith/sortBy的功能及用法
路径
实施
Scala中的排序函数
sortWith函数的语法
def sortWith(lt: (A, A) ⇒ Boolean): List[A]
//sortWith有一个参数:lt:函数
//lt传递两个参数:(A,A):每次取集合中两个元素来处理
//lt返回值:表达式的Boolean值:判断大小的条件
//sortWith的返回值:List[A]:根据判断构建有序的结果
sortWith函数的功能
栗子
集合
val list3 = List(2,4,6,8,9,7,5,3,1)
需求一:对集合进行升序排序
scala> list3.sortWith((a,b) => a < b )
res24: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
需求二:对集合进行降序排序
scala> list3.sortWith((a,b) => a > b )
res25: List[Int] = List(9, 8, 7, 6, 5, 4, 3, 2, 1)
sortBy函数的语法
def sortBy[B](f: (A) ⇒ B)(implicit ord: math.Ordering[B]): List[A]
//sortBy传递一个参数f:函数
//f的参数:A:集合中的每个元素
//f的返回值:B:按照A中的什么进行排序
//sortBy返回的是排序好的结果
sortBy函数的功能
栗子
集合
val list3 = List(2,4,6,8,9,7,5,3,1)
val list4 = List(("zhangsan",20,"male"),("lisi",30,"female"),("wangwu",19,"male"))
需求一:对list3集合进行升序排序
scala> list3.sortBy(x => x)
res26: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
需求二:对list3集合进行降序排序
scala> list3.sortBy(x => -x)
res27: List[Int] = List(9, 8, 7, 6, 5, 4, 3, 2, 1)
需求三:对list4集合按照年龄进行升序排序
scala> list4.sortBy(tuple => tuple._2)
res28: List[(String, Int, String)] = List((wangwu,19,male), (zhangsan,20,male), (lisi,30,female))
需求四:对list4集合按照年龄进行降序排序
scala> list4.sortBy(tuple => -tuple._2)
res29: List[(String, Int, String)] = List((lisi,30,female), (zhangsan,20,male), (wangwu,19,male))
小结
Scala中排序的函数?
sortWith函数的功能?
sortWith函数的语法?
def sortWith((A1,A2) => A1 < A2)
sortBy函数的功能?
sortBy函数的语法?
def sortBy(A => -A):List[A]
排序只有List和Array才有的方法:如果是iterator或者Map集合要进行排序,先转换为List
目标:掌握集合聚合函数reduce的功能及用法
路径
实施
reduce函数的语法
def reduce(op: (A1, A1) ⇒ A1): A1
//reduce传递1个:op
//op传递2个参数:(T, A)
T:临时变量,用于存储中间结果,tmp的初始值为第一个元素
A:集合中的每个元素
//op返回值:A1:聚合的结果
//reduce返回值:A1:聚合的结果
reduce函数的功能
栗子
需求一:对以下集合进行处理,计算所有元素之和
val list3 = List(2,4,6,8,9,7,5,3,1)
需求二:对list3集合进行处理,计算所有元素的乘积
list3.reduce((tmp,item) => tmp*item)
需求三:对list3集合进行处理,计算所有偶数之和
list3.reduce((tmp,item) => tmp+item)
scala> list3.reduce((tmp,item) => {
| println(s"tmp = ${tmp} item = ${item}")
| tmp+item
| })
tmp = 2 item = 4
tmp = 6 item = 6
tmp = 12 item = 8
tmp = 20 item = 9
tmp = 29 item = 7
tmp = 36 item = 5
tmp = 41 item = 3
tmp = 44 item = 1
res32: Int = 45
scala> list3.reduce(_+_)
res35: Int = 45
reduceLeft、reduceRight的功能与用法
语法
def reduce(op: (A1, A1) ⇒ A1): A1
def reduceLeft(f: (B, A) ⇒ B): B
def reduceRight(op: (A, B) ⇒ B): B
功能
栗子
list3.reduceLeft((tmp,item) => {
println(s"tmp = ${tmp} item = ${item}")
tmp+item
})
list3.reduceRight((item,tmp) => {
println(s"tmp = ${tmp} item = ${item}")
tmp+item
})
小结
reduce函数的功能
reduce函数的语法
def reduce(f:(T,A) => B):B
T:临时变量,存储中间结果,第一次初始值为第一个元素
A:每个元素,从第二个元素开始取
B:所有A聚合的结果
reduceLeft、reduceRight的功能与用法
目标:掌握集合聚合函数fold的功能及用法
路径
实施
fold函数的语法
def fold(z: A1)(op: (A1, A1) ⇒ A1): A1
//fold:两个参数
//z:临时变量的初始值
//op:函数:聚合逻辑
(T,A) => B
T:临时变量
A:集合中的每个元素
B:聚合的结果
fold函数的功能
栗子
需求一:对以下集合进行处理
val list3 = List(2,4,6,8,9,7,5,3,1)
需求二:对list3集合进行处理,计算所有元素的乘积
list3.fold(1)((tmp,item) => tmp*item)
list3.fold(1)((tmp,item) => {
println(s"tmp = ${tmp} item = ${item}")
tmp*item
})
需求三:对list3集合进行处理,计算所有元素之和/计算所有偶数之和
list3.fold(0)((tmp,item) => tmp+item)
list3.fold(0)((tmp,item) => {
if(item % 2 == 0) tmp+item
else tmp
})
fold函数与reduce函数的区别
小结
fold函数的功能?
fold函数的语法?
fold(Zero)((T,A) => T):T
Zero:T的初始值
T:临时变量,存储计算的结果
A:每个元素
fold函数与reduce函数的区别?
目标:掌握Scala中类的声明及定义
路径:如何定义一个类?
实施
类的定义
成员属性的定义
成员方法的定义
构建模块
step1:先添加Scala模块支持
step2:创建一个scala目录,设置为root source
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9XxxwbJr-1618468616224)(20210412_Scala(五).assets/image-20210412092532808.png)]
代码实现
/**
* @ClassName Person
* @Description TODO 构建一个Scala Class,定义成员属性和成员方法
* @Date 2021/4/12 9:26
* @Create By Frank
*/
class Person {
//定义成员属性
var name:String = "itcast"
var age:Int = 20
var gender:String = _
val country:String = "China"
//定义成员方法
def sayWhat() = println("What the hell ?")
}
小结
目标:掌握Scala中Object类的设计
路径:为什么Class类中的main方法不能运行?Scala中Object是什么?
实施
JVM中类运行的规则
从类的main方法开始运行
如果一个方法要被调用:必须通过类进行调用
普通类调用方法:new Class().method
静态的调用:Class.method
Java中怎么实现main方法的运行
public static void main(String[] args)
问题:Scala中没有static关键字
解决:Scala中通过特殊的类Object来实现
Scala中Object的设计
代码测试
/**
* @ClassName Person
* @Description TODO 构建一个Scala Class,定义成员属性和成员方法
* @Date 2021/4/12 9:26
* @Create By Frank
*/
class Person {
//定义成员属性
var name:String = "itcast"
var age:Int = 20
var gender:String = _
val country:String = "China"
//定义成员方法
def sayWhat() = println("What the hell ?")
}
object TestPerson{
def main(args: Array[String]): Unit = {
//构建Person类的实例
val person = new Person
//给属性赋值
person.gender = "male"
//调用对象的属性
println(person.name+"\t"+person.gender+"\t"+person.country)
//调用对象的方法
person.sayWhat()
}
}
小结
Scala中Object是什么?
目标:掌握Scala中利用Object的静态特性构建工具类实现
路径:如何调用类中的方法?如何使用Object构建工具类?
实施
调用类中方法的两种方式
工具类
使用Object构建工具类
/**
* @ClassName Session
* @Description TODO 实现Object构建工具类
* @Date 2021/4/12 10:20
* @Create By Frank
*/
class Session {
}
object SessionUtil{
//定义静态成员属性
var session = new Session
//定义静态成员方法
def getSesssion() = this.session
}
object TestSession{
def main(args: Array[String]): Unit = {
//todo:1-正常构建一个Session
val s1 = new Session
//todo:2-构建一个工具类来实现
val s2 = SessionUtil.session //Util.属性
val s3 = SessionUtil.getSesssion() //Util.方法
}
}
小结
目标:掌握Scala中main方法的使用
路径:main方法的功能?main方法是如何定义的?
实施
main方法的功能
main方法的定义及使用
方式一:显示定义
object TestMain01 {
def main(args: Array[String]): Unit = {
println(args(0))
println(args(1))
}
}
方式二:继承APP Trait
/**
* @ClassName TestMain02
* @Description TODO 继承APP的特质来实现main方法的定义运行
* @Date 2021/4/12 10:29
* @Create By Frank
*/
object TestMain02 extends App {
println("itcast")
println("2021-05-01")
}
小结
main方法的功能?
main方法的定义?
方式一:显示定义main方法
def main(args:Array[String]){
方法体
}
方式二:继承APP这个特质
目标:了解Scala中的访问修饰符规则
路径
实施
修饰符类型
Scala中的规则
修饰符的使用规则
修饰符 / 修饰符[访问域]
访问域:包名或者this
栗子
private[cn] val name = "itcast"
代码测试
/**
* @ClassName Dog
* @Description TODO 实现权限的测试,指定修饰符和修饰符的作用域
* @Date 2021/4/12 10:38
* @Create By Frank
*/
class Dog {
//属性
var name:String = "wangcai"
private[this] val age:Int = 20
//方法
private[cn] def sayHello () = println("旺旺 ~ ")
}
object TestDog{
def main(args: Array[String]): Unit = {
val dog = new Dog
//访问属性
// println(dog.name+"\t"+dog.age)
//访问方法
dog.sayHello()
}
小结
目标:掌握Scala中伴生关系的概念及特点
路径:什么是伴生关系?
实施
伴生关系的定义
伴生关系的特点
代码测试
普通类访问对象的私有属性
class Cat {
private var name:String = "Tom"
var country:String = "China"
private def sayHello() = println("Hello ~")
def eatFish() = println("eating ………")
}
object TestCat{
def main(args: Array[String]): Unit = {
val cat = new Cat
println(cat.name + "\t"+cat.country)
cat.eatFish()
cat.sayHello()
}
}
伴生对象访问类的私有属性
/**
* @ClassName Cat
* @Description TODO 测试伴生关系
* @Date 2021/4/12 10:50
* @Create By Frank
*/
class Cat {
private var name:String = "Tom"
var country:String = "China"
private def sayHello() = println("Hello ~")
def eatFish() = println(s"eating ${Cat.fishName}………")
}
object Cat{
private var fishName:String = "shark"
def main(args: Array[String]): Unit = {
val cat = new Cat
println(cat.name + "\t"+cat.country)
cat.eatFish()
cat.sayHello()
}
}
小结
目标:回顾Java中如何定义构造器及其特点
路径
实施
Java中构造器的定义
Java中构造器的分类?
Java中构造器的特点
代码测试
package bigdata.itcast.cn.java.constructDemo;
/**
* @ClassName Pig
* @Description TODO 回顾Java中的构造方式
* @Date 2021/4/12 11:15
* @Create By Frank
*/
public class Pig {
//定义成员属性
private String name = "peiqi";
private int age = 5;
public Pig() {
}
public Pig(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;
}
}
class TestPig{
public static void main(String[] args) {
Pig p1 = new Pig();
//赋值和取值
p1.setAge(10);
System.out.println(p1.getName()+"\t"+p1.getAge());
//有参构造给属性赋值
Pig qiaozhi = new Pig("qiaozhi", 8);
System.out.println(qiaozhi.getName()+"\t"+qiaozhi.getAge());
}
}
小结
目标:掌握Scala中的主构造器定义及使用
路径
实施
Scala中构造器的分类
Scala中主构造器的定义
代码实现
class Person01(var name:String = "itcast",var age:Int ) {
//成员属性
// var name:String = "itcast" //该属性在构造中被定义了,不需要重复定义
var country:String = "China"
var gender:String = "male"
// var age:Int = 19
//成员方法
def sayHello ()= println("Hello,Person ~")
}
object TestPerson01{
def main(args: Array[String]): Unit = {
//在类名的后面定义传递的构造参数
val p1 = new Person01("heima",18)
println(s"${p1.name} ${p1.country} ${p1.gender} ${p1.age}")
p1.sayHello()
//可以通过在主构造中指定默认值来实现无参构造实现
val p2 = new Person01(age = 18)
println(s"${p2.name} ${p2.country} ${p2.gender} ${p2.age}")
p2.sayHello()
}
}
小结
目标:掌握Scala中的辅助构造器定义及使用
路径
实施
辅助构造器的规则
辅助构造器的定义
def this(参数列表){
//第一行必须调用主构造器或者已存在的辅助构造器
}
代码实现
/**
* @ClassName Person01
* @Description TODO 实现辅助构造器的定义
* @Date 2021/4/13 8:18
* @Create By Frank
*/
class Person01(var name:String = "itcast" ) {
//成员属性
// var name:String = "itcast" //该属性在构造中被定义了,不需要重复定义
var country: String = "China"
var gender: String = "male"
var age: Int = 19
//成员方法
def sayHello() = println("Hello,Person ~")
//定义辅助构造器:this方法
def this(name: String, country: String) {
this(name)
this.country = country
}
def this(name:String,country:String,age:Int){
this(name,country)
this.age = age
}
}
object TestPerson01{
def main(args: Array[String]): Unit = {
//在类名的后面定义传递的构造参数
val p1 = new Person01("heima")
println(s"${p1.name} ${p1.country} ${p1.gender} ${p1.age}")
p1.sayHello()
//可以通过在主构造中指定默认值来实现无参构造实现
val p2 = new Person01
println(s"${p2.name} ${p2.country} ${p2.gender} ${p2.age}")
p2.sayHello()
//调用辅助构造器进行构造
val p3 = new Person01("bigdata","巴基斯坦")
println(s"${p3.name} ${p3.country} ${p3.gender} ${p3.age}")
p3.sayHello()
val p4 = new Person01("bigdata","巴基斯坦",100)
println(s"${p4.name} ${p4.country} ${p4.gender} ${p4.age}")
p4.sayHello()
}
}
小结
辅助构造器的规则是什么?
辅助构造器如何实现定义?
def this(构造参数列表){
this(主构造或者辅助构造)
}
目标:apply方法的功能及实现
路径
实施
问题
val a1 = Array(1,2,3,4,5,6)
val a2 = new Array[Int](6)
apply方法的功能
apply方法的实现
代码实现
class Person02(var name:String) {
var age:Int = 20
//辅助构造
def this(name:String,age:Int){
this(name)
this.age = age
}
}
object Person02{
//传递一个参数,进行构造返回
def apply(name: String): Person02 = new Person02(name)
//传递两个个参数,进行构造返回
def apply(name: String,age:Int): Person02 = new Person02(name,age)
}
object TestPerson02{
def main(args: Array[String]): Unit = {
//通过正常的构造来实现对象构建
val p1 = new Person02("itcast")
val p2 = new Person02("itcast",30)
//通过语法糖来实现构造
val p3 = Person02("heima")
val p4 = Person02("heima",40)
}
}
小结
目标:掌握Scala中类的继承与重写
路径
实施
面向对象实现继承的设计
继承本质:决定了这类是什么
Scala中实现类的继承
关键字:extends
class Person03 {
//共同的属性
var name:String = "itcast"
val age:Int = 18
//共同的方法
def sayWhat = println("I am a Human")
}
class Student03 extends Person03{
//定义自己的属性
val stuid:String = "001"
//定义自己的方法
def learning = println("I am Learning")
}
object TestPerson03{
def main(args: Array[String]): Unit = {
val s1 = new Student03
println(s1.stuid)//自己的属性
s1.learning//自己的方法
println(s1.name+"\t"+s1.age) //父类的属性
s1.sayWhat //父类的方法
}
}
如果子类觉得父类的属性或者方法不好怎么办?
Scala中实现方法和属性的重写
class Student03 extends Person03{
//定义自己的属性
val stuid:String = "001"
//定义自己的方法
def learning = println("I am Learning")
//重写父类的属性
override val age: Int = 19
//重写父类的方法
override def sayWhat: Unit = println("I am a Student")
}
Scala中实现不允许子类重写或者访问
小结
目标:掌握Scala中的类型转换与类型判断的方法及实现
路径
实施
子类转父类的实现
定义一个子类,用一个父类对象指向即可
子类中包含了父类中所有的方法和属性,可以直接转换
//构建一个子类的实例,使用父类指向,只能调用父类的属性和方法
val s2: Person04 = new Student04
println(s2.name+"\t"+s2.age)
s2.sayHello
父类转子类的问题
父类不能转换为子类,除非本身指向的就是一个子类的对象才可以实现
必须提前判断,如果不判断,会出现类型转换异常
//例如s2的情况:可以实现将s2转换为一个Student04的对象
s2.asInstanceOf[Student04] //类似于Java中 :Student04 s3 = (Student04)s2
//上面这种写法的前提是:明确的知道s2本质是一个Student04的对象
粗略类型判断与转换
isInstanceOf:用于判断是否是对应的类型
asInstanceOf:用于转换为对应的类型
判断与转换
//实际工作中进行强制类型转换时,先判断后转换,避免程序出错
if(s2.isInstanceOf[Student04]) {
s2.asInstanceOf[Student04]
}
不精准
精准类型判断与转换
getClass:获取对象的类型
ClassOf:获取类的类型
判断与转换
if(s2.getClass == classOf[Student04]){
s2.asInstanceOf[Student04]
}
精准
完整代码
package bigdata.itcast.cn.scala.transDemo
/**
* @ClassName Person04
* @Description TODO
* @Date 2021/4/13 9:34
* @Create By Frank
*/
class Person04 {
var name:String = "itcast"
var age:Int = 20
def sayHello = println("Hello,Person")
}
class Student04 extends Person04 {
var stuId:String = "001"
def sayBye = println("Bye ,Person")
}
object TestPerson04{
def main(args: Array[String]): Unit = {
//构建一个子类的实例,使用子类指向,标准的student类型的对象
val s1: Student04 = new Student04
// println(s1.name+"\t"+s1.age) //父类的
// s1.sayHello
// println(s1.stuId) //子类的
// s1.sayBye
//构建一个子类的实例,使用父类指向,只能调用父类的属性和方法
val s2: Person04 = new Student04
// println(s2.name+"\t"+s2.age)
// s2.sayHello
//如何将一个父类转换为一个子类?:如果一个父类指向的是一个子类的对象才可以实现转换
//例如s2的情况:可以实现将s2转换为一个Student04的对象
// s2.asInstanceOf[Student04] //类似于Java中 :Student04 s3 = (Student04)s2
//上面这种写法的前提是:明确的知道s2本质是一个Student04的对象
//实际工作中进行强制类型转换时,先判断后转换,避免程序出错
// if(s2.isInstanceOf[Student04]) {
// s2.asInstanceOf[Student04]
// }
//这种判断属于粗略的类型判断,不精确
// println(s2.isInstanceOf[Person04])
// println(s2.isInstanceOf[Student04])
// if(s2.getClass == classOf[Student04]){
// s2.asInstanceOf[Student04]
// }
println(s2.getClass == classOf[Person04])
println(s2.getClass == classOf[Student04])
}
}
小结
目标:掌握Scala中抽象类的使用规则及实现
路径
实施
抽象类的设计
抽象类的定义
abstract class Person05 {
//具体的属性
// var name:String = "itcast"
// var age:Int = 20
//抽象的属性
var name:String
var age:Int
//具体的方法
// def sayHello = println("Hello,Person ~")
//抽象的方法
def sayHello
}
抽象类的实现
继承抽象类的子类要么实现所有抽象字段和抽象方法,要么自己本身也是抽象的
实现抽象属性和方法
class Stduent extends Person05 {
override var name: String = "student"
override var age: Int = 18
override def sayHello: Unit = println("Hello,Student ~")
}
继续抽象
abstract class Teacher extends Person05
小结
什么是抽象类?
Scala中如何定义一个抽象类?
abstract class Name{
//抽象字段
//抽象方法
}
Scala中如何实现抽象类的继承?
目标:了解Scala中匿名内部类的使用
路径
实施
匿名内部类的本质
匿名内部类的定义语法
val 变量名称 = new 抽象类/Trait{
//重写属性或者方法
}
匿名内部类的实现
abstract class Person05 {
//具体的属性
// var name:String = "itcast"
// var age:Int = 20
//抽象的属性
var name:String
var age:Int
//具体的方法
// def sayHello = println("Hello,Person ~")
//抽象的方法
def sayHello
}
//如果多次构建这个类的实例
class Stduent05 extends Person05 {
override var name: String = "student"
override var age: Int = 18
override def sayHello: Unit = println("Hello,Student ~")
}
object TestStudent05{
def main(args: Array[String]): Unit = {
//正常通过构建子类的实例,来实现对抽象类的使用
val student = new Stduent05
student.sayHello
//通过匿名内部类实现new 抽象类:一般用于临时的使用一次抽象类或者接口的方法
val person = new Person05 {
override var name: String = "heima"
override var age: Int = 10
override def sayHello: Unit = println("Hello, Person ~")
}
person.sayHello
}
}
小结
匿名内部类的本质?
匿名内部类的语法?
val 变量名 = new 抽象类/Trait{
重写方法
}
Java中排序时:遇到的匿名内部类
list = 1,2,3,4,9,8,7
Collection.sort(list) //升序
Collection.sort(list,new Comparator{
public int compareTo(int a,int b){
}
})
目标:掌握Scala中Trait的定义及使用
路径
实施
Trait的设计及功能
Trait的定义语法
关键字:trait
定义
trait HelloTrait {
//抽象方法
def sayHello
}
trait ByeTrait {
def sayBye
}
Trait的使用
关键字:extends
实现多个关键字:with
class Person06 extends HelloTrait with ByeTrait with Serializable {
//实现接口中的抽象方法
override def sayHello: Unit = println("Hello ~ Person")
override def sayBye: Unit = println("Bye ~ Person")
}
object Person06{
def main(args: Array[String]): Unit = {
val p1 = new Person06
p1.sayHello
p1.sayBye
}
}
小结
什么是Trait?
Trait如何定义?
trait Name{
//抽象方法
}
Trait如何使用?
目标:实现用Trait封装工具类
路径
实施
Trait中的方法定义
Trait实现封装工具类
在Trait中定义具体的方法,所有继承了该Trait的类都具有了该方法
TimeUtils:时间字符串的剪切和拼接
URLUtils:剪切和拼接url
需求:构建一个Trait,实现切分字符串和拼接字符串
测试
trait StringUtilsTrait {
//可以定义抽象方法和属性,当做接口来实现
//可以定义具体的方法和属性
def subStr(str:String,start:Int,len:Int):String = {
str.substring(start,start+len)
}
def concatStr(sep:String,str:String *):String = {
str.mkString(sep)
}
}
object TimeUtils extends StringUtilsTrait {
}
object URLUtils extends StringUtilsTrait{
}
object TestTrait{
def main(args: Array[String]): Unit = {
val str1 = "I"
val str2 = "like"
val str3 = "learning"
println(TimeUtils.subStr(str3,0,5))
println(TimeUtils.concatStr("-",str1,str2,str3))
}
}
小结
目标:掌握Scala中如何在实例中混入Trait的方法
路径
实施
实例混入Trait的介绍
实例混入Trait指的是为了解决相同类的不同实例继承不同Trait的问题
在构建同一个类的实例时,可以指定当前实例化的对象继承哪些Trait
正常的trait的继承:定义类的实现继承
class Person extends Trait
class Person01 extends HelloTrait {
override def sayHello: Unit = println("Hello Person")
}
object TestPerson01{
def main(args: Array[String]): Unit = {
val p1 = new Person01
p1.sayHello
val p2 = new Person01
p2.sayHello
}
}
实例混入trait:指的是可以在构建对象的时候来实现继承Trait
实例混入Trait的语法
val 对象名称 = new 类 with Trait1 with Trait2 ……
实例混入Trait的实现
需求1:对象1能sayHello,对象2不能
class Person01 {
}
object TestPerson01{
def main(args: Array[String]): Unit = {
val p1 = new Person01 with HelloTrait {
override def sayHello: Unit = println(“Hello”)
}
p1.sayHello
val p2 = new Person01
p2.sayHello //报错
}
}
- 需求2:对象1能sayHello,对象2能sayBye
```scala
class Person01 {
}
object TestPerson01{
def main(args: Array[String]): Unit = {
val p1 = new Person01 with HelloTrait {
override def sayHello: Unit = println("Hello")
}
p1.sayHello
val p2 = new Person01 with ByeTrait {
override def sayBye: Unit = println("Bye")
}
p2.sayBye
}
}
需求3:对象1能sayHello,对象1和对象2都能sayBye,对象2能拼接字符串
class Person01 {
}
object TestPerson01{
def main(args: Array[String]): Unit = {
val p1 = new Person01 with HelloTrait with ByeTrait {
override def sayHello: Unit = println("Hello")
override def sayBye: Unit = println("Bye")
}
p1.sayHello
p1.sayBye
val p2 = new Person01 with ByeTrait with StringUtilsTrait {
override def sayBye: Unit = println("Bye")
}
p2.sayBye
p2.concatStr("-","I","like")
}
}
class Person01 extends ByeTrait {
override def sayBye: Unit = println("Bye")
}
object TestPerson01{
def main(args: Array[String]): Unit = {
val p1 = new Person01 with HelloTrait {
override def sayHello: Unit = println("Hello")
}
p1.sayHello
p1.sayBye
val p2 = new Person01 with StringUtilsTrait
p2.sayBye
p2.concatStr("-","I","like")
}
}
小结
什么是实例混入Trait?
实现的语法规则是什么?
val p1 = new Person with Trait1 with Trait2 ……
目标:掌握Scala中Trait的构造机制以及了解Trait继承Class的实现
路径
实施
Trait的构造器
Trait不支持构造参数,但是每个Trait都有一个无参构造器
类中:除了成员属性和成员方法外,其他的所有代码都属于主构造器
class Person02(var name:String,var age:Int) {
println("Start ……………………")
//成员属性
var country :String = "China"
//成员方法
def sayHello = println("Hello")
println("End ……………………")
}
object Person02{
def main(args: Array[String]): Unit = {
val itcast = new Person02("itcast",18)
itcast.sayHello
}
}
类的基本构造顺序
从左到右依次执行继承的父类或者Trait的构造,再执行自身的构造
继承一个类
class Person02() {
println("Start Person ……………………")
println("End Person ……………………")
}
class Student02 extends Person02{
println("Start Student ……………………")
println("End Student ……………………")
}
object Person02{
def main(args: Array[String]): Unit = {
val student = new Student02
}
}
继承一个类和两个Trait
class Person02() {
println("Start Person ……………………")
}
trait HelloTrait1 {
println("Start HelloTrait ……")
}
trait ByeTrait1 {
println("Start ByeTrait ……")
}
class Student02 extends Person02 with HelloTrait1 with ByeTrait1 {
println("Start Student ……………………")
}
object Person02{
def main(args: Array[String]): Unit = {
val student = new Student02
}
}
复杂继承的构造顺序
如果一个类继承多个Trait,而Trait又继承父Trait,先构造父Trait,再构造子Trait
如果多个子Trait的父Trait相同,则父Trait只构造一次
继承关系
```scala
class Student extends Person with MyLogger with TimeLogger
Trait MyLogger extends Logger
Trait TimeLogger extends Logger
```
- 构造顺序
```scala
class Person02() {
println("Start Person ……………………")
}
trait Logger{
println("Strat Logger ……")
}
trait MyLogger extends Logger {
println("Start MyLogger ……")
}
trait TimeLogger extends Logger {
println("Start TimeLogger ……")
}
class Student02 extends Person02 with MyLogger with TimeLogger {
println("Start Student ……………………")
}
object Person02{
def main(args: Array[String]): Unit = {
val student = new Student02
}
}
```
Trait继承Class的实现
class extends Trait:类继承Trait
trait extends Class:Trait继承类
class Person03 {
def sayWhat = println("I like leanring")
}
trait PersonTrait extends Person03{
def sayBye
}
class Student extends PersonTrait{
override def sayBye: Unit = println("bye")
}
object Stduent{
def main(args: Array[String]): Unit = {
val student = new Student
student.sayBye
student.sayWhat
}
}
小结
目标:掌握Scala中的模式匹配的功能及语法
路径
实施
模式匹配的功能
类似于Java中的switch case,对代码中的内容进行判断,根据判断匹配对应的结果
但是功能比Java中的switch case的功能更加强大,可以匹配内容、类型等多种条件
Java中的switch case的语法
switch (变量) {
case value1:
op1
break;
case value2
op2
break;
……
default opN;
}
package bigdata.itcast.cn.java.swithCaseDemo;
import java.util.Scanner;
/**
* @ClassName SwitchDemo
* @Description TODO 测试 Java 中的 switch case
* @Date 2021/4/13 12:51
* @Create By Frank
*/
public class SwitchDemo {
public static void main(String[] args) {
System.out.println("问:你正在打游戏,队友正喊你团一波,这时候你女朋友掉水里的,请问你怎么选?");
System.out.println(" A:继续跟团,不能坑队友");
System.out.println(" B:救女朋友,对象不好找");
System.out.println(" C:不选择,换个游戏也换个女朋友");
System.out.print("请输入你的选项【A/B/C】:");
//构建输入器
Scanner scanner = new Scanner(System.in);
//读取用户输入
String input = scanner.next();
//判断输入
switch (input){
case "A":
System.out.println("U r a bad man");
break;
case "B":
System.out.println("U r a good man");
break;
case "C":
System.out.println("U r a not man");
break;
default:
System.out.println("U hava no choice");
}
}
}
模式匹配的语法
变量 match {
case value1 => operater1
case value2 => operater2
……
case valueN => operaterN
[case _ => default Operator]
}
匹配内容实现
object MatchCaseDemo1 {
def main(args: Array[String]): Unit = {
//输出问题
println("问:你正在打游戏,队友正喊你团一波,这时候你女朋友掉水里的,请问你怎么选?");
println(" A:继续跟团,不能坑队友");
println(" B:救女朋友,对象不好找");
println(" C:不选择,换个游戏也换个女朋友");
print("请输入你的选项【A/B/C】:");
//读取用户输入
val input = StdIn.readLine()
//匹配input的值
input match {
case "A" => println("U r a bad man")
case "B" => println("U r a good man")
case "C" => println("U r a not man")
case _ => println("U have not a choice")
}
}
}
小结
什么是模式匹配?
类似于Java中的switch case,但是功能更加强大
如何实现模式匹配?
变量 match {
case v1 => op1
case v2 => op2
……
case _ => opN
}
目标:掌握Scala中模式匹配类型及守卫条件的实现
路径
实施
模式匹配类型实现
功能:判断变量的类型,根据不同类型实现不同的操作
应用:一般用于实现异常捕获
object MatchCaseDemo2 {
def main(args: Array[String]): Unit = {
//定义一个数组
val arr = Array(1,2,true,14.98,"itcast")
//取出元素,输出对应的元素的值和类型
val input = arr(Random.nextInt(arr.length))
input match{
case x:Int => println(s"type:Int,value:${x}")
case y:Double => println(s"type:Double,value:${y}")
case m:String => println(s"type:String,value:${m}")
case n:Boolean => println(s"type:Boolean,value:${n}")
case _ => println("这是其他类型")
}
}
}
守卫条件的实现
在匹配时,可以指定匹配条件,如果不满足匹配的守卫条件,依旧不会匹配成功
object MatchCaseDemo2 {
def main(args: Array[String]): Unit = {
//定义一个数组
val arr = Array(1,2,true,14.98,"itcast")
//取出元素,输出对应的元素的值和类型
val input = arr(0)
input match{
case x:Int if (x > 1) => println(s"type:Int,value:${x}")
case y:Double => println(s"type:Double,value:${y}")
case m:String => println(s"type:String,value:${m}")
case n:Boolean => println(s"type:Boolean,value:${n}")
case _ => println("这是其他类型")
}
}
}
小结
目标:了解如何对数组、集合、元组进行模式匹配
路径
实施
模拟匹配数组
object MatchCaseDemo3 {
def main(args: Array[String]): Unit = {
//定义一个数组
val arr: Array[Int] = Array(1,4,7)
//匹配数组
arr match{
case Array(0) => println(s"这个数组中只有一个元素,为0")
case Array(1,2,3) => println(s"这个数组中有三个个元素,为1,2,3")
case Array(1,x,y) => println(s"这个数组中有三个个元素,第一个元素肯定为1")
case Array(0,_*) => println(s"这个数组中有多个元素,第一个元素肯定是0")
case _ => println("这是其他类型数组")
}
}
}
模式匹配集合
object MatchCaseDemo3 {
def main(args: Array[String]): Unit = {
//定义一个数组
val list = List(
1,2)
//匹配数组
list match{
case List(1,2) => println(s"只有两个元素,为1,2")
case x::y::Nil => println(s"只有两个元素,元素值任意")
case 1::Nil => println(s"只有1个元素,元素值1")
case 1::tail => println(s"第一个元素是1,其他的元素是任意的")
case _ => println(“这是其他类型”)
}
}
}
```
模式匹配元组
object MatchCaseDemo3 {
def main(args: Array[String]): Unit = {
//定义一个数组
val tuple = (3,3,3)
//匹配数组
tuple match{
case (1,2,x) => println(s"元素的值为1,2和任意一个")
case (x,3,z) => println(s"第二个元素值必须为3")
case (x,y,z)=> println(s"元素值任意")
case _ => println("这是其他类型")
}
}
}
小结
目标:掌握Scala中如何在申明变量时进行匹配取值
路径
实施
数据处理时的常见问题
如果有一个Array数组,总共4个元素,我们需要取出数组中的每个元素,单独处理,怎么取?
val array = Array(100,20,40,30) //sum,avg,max,min
sum = array(0)
avg = array(1)
max = array(2)
min = array(3)
for(i <- array)
如果有一个List集合,每个元素都由4个字段构成,我想取出每个元素中的第二列和第三列,怎么取?
val list = List("1 zhangsan 18 male","2 lisi 20 female","3 wangwu 22 male")
list.map(line => {
val arr = line.split(" ")
val name = arr(1)
val age = arr(2)
(name,age)
})
如果有一个Map集合,每个元素的Value是二元组类型,格式为:(id,(name,age)) 要取出三列,怎么取?
val map = Map((1,("zhangsan",18)),(2,("lisi",20)),(3,("wangwu",22)))
map.foreach(tuple => {
val id = tuple._1
val name = tuple._2._1
val age = tuple._2._2
println(id+"\t"+name+"\t"+age)
})
声明变量取值的设计
声明变量取值的实现
如果有一个Array数组,总共4个元素,我们需要取出数组中的每个元素,单独处理,怎么取?
val array = Array(100,20,40,30)
val Array(sum,avg,max,min) = array
如果有一个List集合,每个元素都由4个字段构成,我想取出每个元素中的第二列和第三列,怎么取?
val list = List("1 zhangsan 18 male","2 lisi 20 female","3 wangwu 22 male")
list.map(line => {
val Array(_,name,age,_) = line.split(" ")
(name,age)
})
如果有一个Map集合,每个元素的Value是二元组类型,格式为:(id,(name,age)) 要取出三列,怎么取?
val map = Map((1,("zhangsan",18)),(2,("lisi",20)),(3,("wangwu",22)))
map.foreach{
case (id,(name,age)) => println(id+"\t"+name+"\t"+age)
}
小结
目标:掌握Scala中样例类的设计、功能与特点
路径
实施
样例类的设计
Scala中一种特殊的类,通过关键字标识:case
正常的类
class Name
样例类
case class Name
可以用封装数据,类似于Java中构建的JavaBean或者POJO类设计
一般也用于模式匹配
样例类的功能与特点
普通类:所有的方法需要自己手动显示的定义
class Person06(var name:String){
// override def toString: String = this.name
//重写hashcode进行比较,以name实现,只要name对应的hashcode一样,认为是一样的
//注意:name如果不一样,但是hash是可能一样的
override def hashCode(): Int = super.hashCode()
//如果hashcode一样,通过equals来比较值
override def equals(obj: Any): Boolean = super.equals(obj)
}
object TestPerson06{
def main(args: Array[String]): Unit = {
val p1 = new Person06("itcast")
//没有定义apply,必须给new关键字
val p2 = new Person06("itcast")
//打印:调用toString
println(p1)
println(p2)
//实现两个对象的比较
println(p1 == p2)
}
}
样例类:自动构建伴生对象,自动实现重写了以下方法
case class Person08(var name:String) {
}
object TestPerson08{
def main(args: Array[String]): Unit = {
//构建实例:自动生成伴生对象,实现apply方法
val p1 = Person08("itcast")
val p2 = Person08("itcast")
//打印:调用toString,自动实现了toString
// println(p1)
//比较:只要name相同,就认为相同,自动实现了hashcode和equals
println(p1 == p2)
}
}
apply:样例类自动构建伴生对象,自动生成apply
toString:样例类自动重写
hashCode and equals:样例类自动重写
copy:直接复制一个样例类的对象
val p3 = p2.copy("heima")
unapply:提取器
小结
目标:掌握样例类如何实现模式匹配
路径
实施
实现样例类的模式匹配
//样例类
case class Person01(var name:String,var age:Int)
//样例对象:全局唯一实例,静态的
case object Dog01
//普通类
class Cat(var name:String,var age:Int)
object matchCaseClassDemo {
def main(args: Array[String]): Unit = {
//构建一个数组:放三种类型
val arr = Array(Person01("itcast",20),new Cat("Tom",19),Dog01)
//随机取一个元素
val input = arr(Random.nextInt(arr.length))
//对元素模式匹配
input match{
// case x:Cat => println(s"this type is Cat name = ${x.name} age = ${x.age}")
case Cat(name,age) => println(s"this type is Cat name = ${x.name} age = ${x.age}")
// case y:Person01 => println(s"this type is Person name = ${y.name} age = ${y.age}")
case Person01(name,age) => println(s"this type is Person name = ${name} age = ${age}")
case Dog01 => println("this is a Dog")
}
}
}
样例类与普通类模式匹配的区别
普通类:匹配类的类型,然后传递给对象,通过对象获取类的属性
样例类:直接匹配类的属性,然后复制给属性变量
小结
样例类的模式匹配与普通类有什么区别?
目标:掌握Scala中的unapply方法与提取器的使用
路径
实施
unapply的功能
unapply的功能:传递对象,返回对象中的属性,实现模式匹配的时候,直接匹配属性的值
unapply的定义及使用
case class Dog(var name:String,var age:Int)
class Cat(var name:String,var age:Int)
object UnapplyDemo {
def main(args: Array[String]): Unit = {
val arr = Array(Dog("wangwang",5),new Cat("tom",8))
val input = arr(Random.nextInt(arr.length))
input match {
case Dog(name,age) => println(s"this is a dog name =${name} age = ${age}" )
case cat:Cat => println(s"this is a cat name =${cat.name} age = ${cat.age}" )
}
}
}
case class Dog(var name:String,var age:Int)
class Cat(var name:String,var age:Int)
object Cat{
//传递参数,返回对象
def apply(name:String,age:Int) = new Cat(name,age)
//传递对象,返回参数
def unapply(cat: Cat): Option[(String, Int)] = {
//判断对象是否为空
if(cat != null){
Some((cat.name,cat.age))
}else{
None
}
}
}
object UnapplyDemo {
def main(args: Array[String]): Unit = {
//问题1:如何能让Cat在构建实例的时候,不写new
val arr = Array(Dog("wangwang",5),Cat("tom",8))
val input = arr(Random.nextInt(arr.length))
input match {
case Dog(name,age) => println(s"this is a dog name =${name} age = ${age}" )
//问题2:如何能让Cat在模式匹配时直接匹配属性
case Cat(name,age) => println(s"this is a cat name =${name} age = ${age}" )
}
}
}
小结
unapply的功能?
unapply的定义及使用?
def unapply(类的对象) = Option[(属性的值)]
目标:掌握Scala中Option类型的定义及使用
路径
实施
Option类型的设计
Option类型的定义
Option类型的使用
object OptionDemo {
def main(args: Array[String]): Unit = {
val map = Map("1" -> "zhangsan","2"->"lisi")
//根据Key取值
//方式一
// println(map("11"))
//方式二
// val x: Option[String] = map.get("11")
//方式三
println(map.getOrElse("11","null"))
}
}
小结
目标:了解偏函数的功能及使用
路径
实施
偏函数的功能
偏函数的定义
偏函数是指代码块中没有match的一组case语句就是偏函数
偏函数本质是PartialFunction[A, B]的一个实例
定义
val pf = {
case 语句
}
偏函数的使用
方式一:直接定义调用:定义一个方法,传递int类型数字,返回对应的汉字
//普通方法定义
def m1(numb:Int):String = {
numb match{
case 1 => "一"
case 2 => "二"
case 3 => "三"
case _ => "其他"
}
}
println(m1(2))
object PfDemo {
def main(args: Array[String]): Unit = {
//直接定义一个偏函数
val pf:PartialFunction[Int,String] = {
case 1 => "一"
case 2 => "二"
case 3 => "三"
case _ => "其他"
}
println(pf(1))
}
}
方式二:搭配collect函数使用,collect类似于map函数,传递参数为偏函数
//将所有的数值元素乘以10
val array = Array(1,2,3,9,"itcast",true)
//正常的写法
array.filter(x => x.isInstanceOf[Int]).map(x => x.asInstanceOf[Int] * 10).foreach(println)
val pf2:PartialFunction[Any,Int] = {
case i:Int => i * 10
}
//collect方法,类似于map方法,collect方法只能传递偏函数
array.collect(pf2).foreach(println)
小结
目标:了解Scala中如何使用正则表达式
路径
实施
正则类Regex的功能
正则表达式的使用方式
object RegexDemo {
def main(args: Array[String]): Unit = {
//对邮箱格式的正则匹配
val str1 = "[email protected]"
val str2 = "12345@qq"
//构建邮箱格式正则
val regex: Regex = """.+@.+\..+""".r
//匹配
val matches: Iterator[Regex.Match] = regex.findAllMatchIn(str2)
matches.foreach(println)
}
}
小结
目标:掌握Scala中如何实现异常的处理
路径
实施
捕获异常try catch的使用
关键字:try catch finally
实现
object ExceptionDemo {
def main(args: Array[String]): Unit = {
//定义一个数值的字符串
val i = "0"
try{
//实现数据计算
println(1 / i.toInt)
}catch {
case e1:NumberFormatException => println("数字转换异常:"+ e1.getMessage)
case e2:ArithmeticException => println("数学规则异常:"+e2.getMessage)
case e3:Exception => println("其他异常")
}finally {
println("不论你是否有异常,我都会执行")
}
}
}
抛出异常throw Exception
throw new Exception("就是想抛一个异常")
小结
目标:了解Scala中泛型、上下界及斜变逆变的使用
路径
实施
泛型的概念及使用
泛型的概念:用于定义不确定的数据类型,实现可以使用不同类型进行传递
泛型的使用
规则:
需求1:定义一个方法,传递任意类型的数组,输出数组中的每个元素
object FanXingDemo {
def main(args: Array[String]): Unit = {
val a1: Array[Int] = Array(1,2,3)
val a2: Array[String] = Array("a","b","c")
//普通的方法
def m1(array:Array[Int]) = array.foreach(println)
// m1(a1)
// m1(a2)
//传递一个任意类型的数组
def m2[A](array:Array[A]) = array.foreach(println)
m2(a1)
m2(a2)
}
}
需求2:定义一个类,允许传递两个泛型属性
case class PersonFanxing[B](var name:B,var age:B)
object FanXingDemo {
def main(args: Array[String]): Unit = {
//构建PersonFanxing的实例
PersonFanxing("itcast",18)
PersonFanxing(19,18)
PersonFanxing("itcast","heima")
}
}
上下界的概念及使用
上界:指定泛型的范围只能是该类或者该类的子类,不能超过这个类的范围
语法
[T <: B] //T为泛型,B为上界类型,T必须是B类型或者B的子类类型
下界:指定泛型的范围只能是该类或者该类的父类,不能低于这个类的范围
语法
[T >: B] //T为泛型,B为下界类型,T必须是B类型或者B的父类类型
测试
正常的调用
class Things
class Persons extends Things
class Students extends Persons
object UpAndDownDemo {
def main(args: Array[String]): Unit = {
def demo[T](a:Array[T]) = a.foreach(println)
demo(Array(new Things,new Things))
demo(Array(new Persons,new Persons))
demo(Array(new Students,new Students))
}
}
限制上界
def main(args: Array[String]): Unit = {
def demo[T <: Persons](a:Array[T]) = a.foreach(println)
demo(Array(new Things,new Things)) //报错
demo(Array(new Persons,new Persons))
demo(Array(new Students,new Students))
}
限制下界
object UpAndDownDemo {
def main(args: Array[String]): Unit = {
def demo[T >: Persons](a:Array[T]) = a.foreach(println)
demo(Array(new Things,new Things))
demo(Array(new Persons,new Persons))
demo(Array(new Students,new Students)) //编译时报错
}
}
非变斜变逆变的概念及使用
非变【A】:两个类之间的关系不可延伸,就是非变
斜变【+A】:两个类之间的关系可以延伸且不变,就是斜变
tmp1 = Temp[String]
tmp2 :Temp[Object]
tmp2 = tmp1
逆变【-A】:两个类之间的关系延伸以后转换了,就是逆变
tmp1:Temp[String]
tmp2 = Temp[Object]
tmp1 = tmp2
例子
class Super
class Sub extends Super
class Temp1[T]
class Temp2[+T]
class Temp3[-T]
def main(args: Array[String]): Unit = {
val a:Temp1[Sub] = new Temp1[Sub]
// 编译报错
// 非变
val b:Temp1[Super] = a
// 协变
val c: Temp2[Sub] = new Temp2[Sub]
val d: Temp2[Super] = c
// 逆变
val e: Temp3[Super] = new Temp3[Super]
val f: Temp3[Sub] = e
}
小结
目标:了解Scala中的柯里化函数的实现
路径
实施
Scala中常用的函数类型
匿名函数:没有名字的函数,只有参数列表和函数体
(x:Int,y:Int) => {函数体}
值函数:将匿名函数赋值给一个变量,取个名字
val fname = (x:Int,y:Int) => {函数体}
高阶函数:函数A的参数是一个函数,A就为高阶函数
f1(f:A => B)
柯里化函数的功能及特点
柯里化函数的定义及实现
需求:传递两个参数,实现求和
实现1:正常函数定义
scala> def m1(x:Int,y:Int) = x + y
m1: (x: Int, y: Int)Int
方法名:(参数列表)返回值
scala> m1(1,3)
res1: Int = 4
- 实现2:柯里化函数定义
```scala
scala> def m2(x:Int)(y:Int) = x + y
m2: (x: Int) (y: Int)Int
方法名:(参数列表) 返回值
scala> m2(1,3)
<console>:13: error: too many arguments for method m2: (x: Int)(y: Int)Int
m2(1,3)
^
scala> m2(1)(3)
res3: Int = 4
scala>
基本原理:实现函数的分步调用
scala> m2(1)_
res4: Int => Int = <function1>
scala> res4(3)
res5: Int = 4
自己写这个函数代替柯里化函数
def m3(x:Int) = (y:Int) => x + y
def m3(x:Int) = {
//返回值是一个函数
(y:Int) => x + y
}
scala> def m3(x:Int) = (y:Int) => x + y
m3: (x: Int)Int => Int
scala> m3(1)
res6: Int => Int = <function1>
scala> res6(3)
小结
目标:了解高阶函数闭包函数的概念及用法
路径
实施
闭包函数的概念及特点
闭包函数的定义及实现
需求:传递两个参数,实现求和
方式1:普通函数
def m1(x:Int,y:Int) = x + y
方式2:闭包函数
val y = 10
def m2(x:Int) = x + y
小结
目标:了解Scala中隐式转换的功能及特点
路径
实施
问题:Int类没有to方法,但是为什么可以调用?
1.to(10)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vcqinBDa-1618468925526)(20210415_Scala(八).assets/image-20210415103734958.png)]
隐式转换的功能与特点
隐式参数的使用
通过implicit标识参数
当遇到错误需要使用隐式参数时,会自动调用填充
正常参数调用
scala> def m1(x:Int) = println(x)
m1: (x: Int)Unit
scala> m1(1)
1
scala> m1(2)
2
scala> m1
<console>:13: error: missing argument list for method m1
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `m1 _` or `m1(_)` instead of `m1`.
m1
隐式参数调用
scala> implicit var i:Int = 8
i: Int = 8
scala>
scala> def m2(implicit x:Int) = println(x)
m2: (implicit x: Int)Unit
scala> m2(9)
9
scala> m2
8
小结
目标:掌握Scala中隐式转换方法的使用
路径
实施
隐式转换的原则
无歧义
在使用隐式参数的时候 编译器是通过类型进行填充的
当作用域中有多个同类型的隐式参数 在进行填充的就会有歧义 报错
scala> implicit var i:Int = 8
i: Int = 8
scala>
scala> def m2(implicit x:Int) = println(x)
m2: (implicit x: Int)Unit
scala> m2(9)
9
scala> m2
8
scala> implicit var u:Int = 10
u: Int = 10
scala> m2
<console>:15: error: ambiguous implicit values:
both method i of type => Int
and method u of type => Int
match expected type Int
m2
显示操作先行
隐式转换是编译期间程序出错的时候才会尝试进行的机制
如果正常编译程序不出错 没有问题 即使定义隐式参数或者隐式方法 也不会生效
集中定义原则
为了避免冲突,隐式转换方法或者参数要求定义在object中, 静态特性
哪里需要隐式转换哪里手动导入
隐式转换方法的实现
当遇到需要转换的情况时,底层自动调用转换方法实现
class SuperMan(var name:String){
def fly = println("I can fly")
}
class Man(var name:String){
def eat = println("I can eat")
}
object ImplicitDemo {
def main(args: Array[String]): Unit = {
implicit def manToSuperMan(man:Man):SuperMan = {
new SuperMan(man.name)
}
val man = new Man("itcast")
man.eat
man.fly
}
}
小结
文章浏览阅读3.8k次,点赞9次,收藏28次。直接上一个工作中碰到的问题,另外一个系统开启多线程调用我这边的接口,然后我这边会开启多线程批量查询第三方接口并且返回给调用方。使用的是两三年前别人遗留下来的方法,放到线上后发现确实是可以正常取到结果,但是一旦调用,CPU占用就直接100%(部署环境是win server服务器)。因此查看了下相关的老代码并使用JProfiler查看发现是在某个while循环的时候有问题。具体项目代码就不贴了,类似于下面这段代码。while(flag) {//your code;}这里的flag._main函数使用while(1)循环cpu占用99
文章浏览阅读347次。idea shift f6 快捷键无效_idea shift +f6快捷键不生效
文章浏览阅读135次。Ecmacript 中没有DOM 和 BOM核心模块Node为JavaScript提供了很多服务器级别,这些API绝大多数都被包装到了一个具名和核心模块中了,例如文件操作的 fs 核心模块 ,http服务构建的http 模块 path 路径操作模块 os 操作系统信息模块// 用来获取机器信息的var os = require('os')// 用来操作路径的var path = require('path')// 获取当前机器的 CPU 信息console.log(os.cpus._node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是
文章浏览阅读10w+次,点赞435次,收藏3.4k次。SPSS 22 下载安装过程7.6 方差分析与回归分析的SPSS实现7.6.1 SPSS软件概述1 SPSS版本与安装2 SPSS界面3 SPSS特点4 SPSS数据7.6.2 SPSS与方差分析1 单因素方差分析2 双因素方差分析7.6.3 SPSS与回归分析SPSS回归分析过程牙膏价格问题的回归分析_化工数学模型数据回归软件
文章浏览阅读7.5k次。如何利用hutool工具包实现邮件发送功能呢?1、首先引入hutool依赖<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.19</version></dependency>2、编写邮件发送工具类package com.pc.c..._hutool发送邮件
文章浏览阅读867次,点赞2次,收藏2次。docker安装elasticsearch,elasticsearch-head,kibana,ik分词器安装方式基本有两种,一种是pull的方式,一种是Dockerfile的方式,由于pull的方式pull下来后还需配置许多东西且不便于复用,个人比较喜欢使用Dockerfile的方式所有docker支持的镜像基本都在https://hub.docker.com/docker的官网上能找到合..._docker安装kibana连接elasticsearch并且elasticsearch有密码
文章浏览阅读1.3w次,点赞57次,收藏92次。整理 | 郑丽媛出品 | CSDN(ID:CSDNnews)近年来,随着机器学习的兴起,有一门编程语言逐渐变得火热——Python。得益于其针对机器学习提供了大量开源框架和第三方模块,内置..._beeware
文章浏览阅读7.9k次。//// ViewController.swift// Day_10_Timer//// Created by dongqiangfei on 2018/10/15.// Copyright 2018年 飞飞. All rights reserved.//import UIKitclass ViewController: UIViewController { ..._swift timer 暂停
文章浏览阅读986次,点赞2次,收藏2次。1.硬性等待让当前线程暂停执行,应用场景:代码执行速度太快了,但是UI元素没有立马加载出来,造成两者不同步,这时候就可以让代码等待一下,再去执行找元素的动作线程休眠,强制等待 Thread.sleep(long mills)package com.example.demo;import org.junit.jupiter.api.Test;import org.openqa.selenium.By;import org.openqa.selenium.firefox.Firefox.._元素三大等待
文章浏览阅读3k次,点赞4次,收藏14次。Java软件工程师职位分析_java岗位分析
文章浏览阅读2k次。Java:Unreachable code的解决方法_java unreachable code
文章浏览阅读1w次。1、html中设置标签data-*的值 标题 11111 222222、点击获取当前标签的data-url的值$('dd').on('click', function() { var urlVal = $(this).data('ur_如何根据data-*属性获取对应的标签对象