前言
Spark是大数据计算框架,为了能够更好的学习spark,我们需要先了解它的编写语言—Scala
一、Scala与Java之间的关系?
Scala是基于Java编写的
通过上图我们不难发现,scala是通过scalac编译器编译成class文件的,再通过JVM运行。
- Scala是一门多范式的编程语言,Scala支持面向对象和函数式编程。
- Scala源代码(.scala)会被编译成Java字节码(.class),然后运行于JVM之上,并可以调用现有的Java类库,实现两种语言的无缝对接。
- Scala单作为一门语言来看,非常的简洁高效。
二、变量和数据类型
1.标识符命名规范
Java | Scala |
---|---|
字母、数字、下划线组成,首字母不能为数字 | 字母、数字、下划线、特殊符号,首字母不能是数字 |
一般驼峰原则 | 一般驼峰原则 |
2.变量的定义
定义语法:var\val 变量名:[变量类型] = 值
var:定义的变量可以重新赋值
val:定义的变量不能重新赋值
3.字符串获取方式
Java中的方式:
- 直接定义【String name = “yilei”】
- 通过new的方式【new String(“yilei”)】
- 字符串拼接【“hello”+“world”】
- toString、subString等方法
Scala中的方式:
- 直接定义:
通过双引号:val name : “yilei”
通过三引号:
val sql =
"""
|create table xx(
| id int,
| name string,
| age int)
""".stripMargin
- 通过new的方式
val address = new String(“shenzhen”) - 字符串拼接
val result = name + address
val result2 = s"${name} ${address} ${1+1}" - 字符串填充
java中:
String a = String.format("yilei=%s","youxiu");
scala中:
val url = "yilei=%s".format("youxiu")
4.键盘输入
//从控制台读取一行字符串
val line = StdInt.readLine("请输入一行语句:")
println(line)
//从文件读取数据
Source.fromFile("d:data.txt","utf-8").getLines().foreach(println(_))
5.数据类型关系
Java的数据类型:
基本数据类型:byte、short、int、long、float、double、boolean、char
引用数据类型:String、对象、数组、集合
Scala的数据类型:
1、Any:所有类的父类,类似java的Object
2、————AnyVal:值类型
————————Byte、Short、Int、Long、Float、Double、Boolean、Char
————————Unit:相当java的void,有一个实例 (),一般用于方法的返回值
————————StringOps:是对java中的字符串的补充
3、————AnyRef:引用类型
————————String、java对象、java集合、java数组
————————scala对象、scala集合、scala数组
————————————Null:是所有引用类型的子类,有一个实例null,一般用于给引用数据类类型赋初始值;若使用null给引用数据类型赋初始值时,必须指明数据的类型
4、—————————————————Nothing:所有类型的子类,一般是Scala使用,用于异常抛出
6.数据类型之间的转换
1)数据与数据之间的转换
- 低精度转高精度:scala中低精度能够自动转成高精度的数字
- 高精度转低精度:通过toXXX方法转换
var a:Int = 100
var b:Long = a
val q:Double = 100
val w:Float = q.toFloat
2)数据与字符串之间的转换
- 数字转字符串:通过插值表达式与toString方法
- 字符串转数据:通过toXXX方法
val q : Double = 10.0
val s : String = s"${q}"
val s2 : String = q.toString
val p : String = "10.0"
val d : Double = p.toDouble
三、运算符
类型 | Java | Scala |
---|---|---|
算术运算符 | + - * / % ++ – | + - * / % |
逻辑运算符 | 与(&&)、或(\)、非(!) | 与(&&)、或(\)、非(!) |
位运算符 | << >> >>> 按位与() 按位与(&) | << >> >>> 按位与() 按位与(&) |
比较运算符 | == > < >= <= != | == > < >= <= != |
赋值运算符 | = += -= *= /= | = += -= *= /= |
三元运算符 | 布尔表达式? 值1:值2 | 无 |
四、流程控制*
Java | Scala |
---|---|
if … else | if … else |
for… | for… |
while … do…while | while … do…while |
switch | 代码块 |
1.代码块*
语法:{代码块}
特点:块表达式有返回值,返回值是{}中做后一个表达式执行的结果值
val block = {
println("这是一个代码块!")
val name : String = null
println(name)
val age = 20
age
}
println(block)
执行结果:
这是一个代码块!
null
20
2.if … else*
Scala中if语句有返回值,返回值是符合条件的分支{}中最后一个表达式的结果值
val aa = 100
val result = if (aa%2==0){
println("aa是一个偶数")
aa
}else{
println("aa是一个奇数")
}
println(result)
执行结果
aa是一个偶数
100
3.for循环*
java中的for循环:
普通for循环:for(int i = 0 ; i<=100; i++)
增强for循环:for(类型 变量 : 集合/数组)
Scala中的for循环:
to方法:start.to(end) 生成的结果左右闭合
until方法:start.until(end) 生成的结果是左闭右开
//基本用法
for(i <- 1 to 5){
println(s"i=$i")
}
println("="*20)
//守卫
for(j<- 1 to 5 if j%2==0){
print(j)
}
println()
println("="*20)
//步长
for(k<- 1 to 10 by 2){
println(k)
}
println("="*20)
//嵌套for循环
for( l <- 1 to 5;m <- 1 to 5){
print(l+"+"+ m+"\t")
}
println()
println("="*20)
//嵌套for环循+守卫
for( l <- 1 to 5 if l%2==0;m <- 1 to l){
print(l+"+"+ m +"\t")
}
println()
println("="*20)
//嵌入变量
for( n <- 1 to 5;m <- n+1 to 5){
print(n+"+"+ m+"\t")
}
println()
for( n <- 1 to 5; k=n+1 ;m <- k to 5){
print(n+"+"+ m+"\t")
}
println()
println("="*20)
//yield表达式能够让for循环有返回值
var res = for(n <- 10 to 15) yield {
print(n+"\t")
n + 1
}
println()
println(res)
执行结果:
i=1
i=2
i=3
i=4
i=5
====================
24
====================
1
3
5
7
9
====================
1+1 1+2 1+3 1+4 1+5 2+1 2+2 2+3 2+4 2+5 3+1 3+2 3+3 3+4 3+5 4+1 4+2 4+3 4+4 4+5 5+1 5+2 5+3 5+4 5+5
====================
2+1 2+2 4+1 4+2 4+3 4+4
====================
1+2 1+3 1+4 1+5 2+3 2+4 2+5 3+4 3+5 4+5
1+2 1+3 1+4 1+5 2+3 2+4 2+5 3+4 3+5 4+5
====================
10 11 12 13 14 15
Vector(11, 12, 13, 14, 15, 16)
4.while*
while与do-while的区别:
while循环是先判断再执行;do-while是先执行再判断,并且一定会执行一次
var i = 6
while (i<=5){
println(i)
i = i+1
}
var j = 6
do{
println(j)
j = j+1
}while(j<=5)
5.Scala中没有break与continue关键字咋办?*
第一步导入包:
import scala.util.control.Breaks._
第二步:通过breakable与break实现,类似try{} catch{}
//相当于break
breakable{
for(i<-1 to 5){
if(i==3)break()
println(i)
}
}
//相当于continue
for(i<-1 to 5){
breakable{
if(i==3) break()
println(i)
}
}
五、函数式编程*
不管Java还是Scala对象是对属性及方法的封装
说在前面:方法可以是函数,函数也是对象
1.方法*
**语法:**def 方法名(参数1:参数类型,…)={方法体}
def add(x:Int,y:Int):Int={x+y}
定义在方法中的方法可以当作函数
def main(args: Array[String]): Unit = {
def add1(a:Int):String={
a.toString
}
}
方法简化:
简化原则:
- 如果方法体中只有一行语句可以省略{}
def add2(x:Int,y:Int):Int=x+y
- 如果方法是将方法体的{}中最后一个表达式作为方法的返回值,那返回值类型可以省略;scala会自行推断(如果方法体中有return关键字,则方法必须定义返回值类型)
def add3(x:Int,y:Int)=x*y
- 如果方法不需要返回值,那么=可以省略,但是=与{}不能同时省略
def add4(x:Int){println(x)}
//同时省略=与{}不行
//def add5(x:Int)println(x)
- 如果方法不需要参数,那么在定义方法时()可以省略
注意:
1.如果定义方法的时候没有带上(),那么在调用的时候也不能带上()
2.如果定义方法的时候有带上(),那么在调用时可带可不带
object test06 {
def main(args: Array[String]): Unit = {
add
println(add)
add1()
println(add1())
add1
println(add1)
}
def add:String={"hello world"}
def add1():String={"hello world"}
}
执行结果:
hello world
hello world
hello world
参数定义形式:
- 参数名:参数类型
def getName(str:String):String={"name=${str}"}
- 默认值
object test06 {
def main(args: Array[String]): Unit = {
println(getAge())
}
def getAge(x:Int=10)={s"age=${x}"}
}
- 可变参数
注意:
1、一个方法中只能有一个可变参数,并且可变参数只能放在最后;并且一旦含有可变参数的话,就不能与默认值使用。
2、java中可将数组作为可变参数传给相应方法
3、Scala中想要将集合/数组的所有元素传入可变参数是通过: 数组/集合 : _*
object test10 {
def main(args: Array[String]): Unit = {
println(add(1, 2, 3))
}
def add(x:Int*):Int={x.sum}
}
object test10 {
def main(args: Array[String]): Unit = {
println(add1(2,3,4,5,6))
}
def add1(x:Int,y:Int*)={x*y.sum}
}
小练习:获取前七天的业务数据的路径
object test10 {
def main(args: Array[String]): Unit = {
val arr = getTime(7)
//数组不可直接当做可变参数传入
println(getPath(arr: _*))
}
def getTime(n:Int)={
//获取当天时间
val dateTime = LocalDateTime.now()
for(i <- 1 to n)yield{
//获取前i天时间
val time = dateTime.plusDays(-i)
val str = time.format(DateTimeFormatter.ofPattern("yyyyMMdd"))
str
}
}
def getPath(x:String*)={
for(i <- x)yield{
s"/user/hive/warehose/user_info/${i}"
}
}
}
- 带名参数
直接在调用方法的时候将参数值指定传递给哪个参数
2.函数*
- 语法:val 函数名 = (参数名:参数类型,…) =>{函数体}
函数没有定义返回值的地方,函数的返回值就是函数体中最后一个表达式的结果值。
object test11 {
def main(args: Array[String]): Unit = {
val add = (a:Int,b:Int)=>{a+b}
println(add(1,10))
}
}
- 函数简化:如果函数体中只有一行语句,{}可以省略
object test11 {
def main(args: Array[String]): Unit = {
val add = (a:Int,b:Int)=>a+b
println(add(1,10))
}
}
3.方法与函数的区别*
- 1、方法如果定义在object/class中是可以重载的,函数不可以
- 2、方法是存储在方法中,函数是对象是存储在堆中
- 3、方法如果定义在方法中,其实就是函数,不可以重载
联系:方法可以转成函数: 方法名+空格+_
object test11 {
def main(args: Array[String]): Unit = {
val func = add _
}
def add(x:Int,y:Int) = x * y
}
4.高阶函数*
定义:以函数作为参数或者返回值的方法/函数
object test11 {
def main(args: Array[String]): Unit = {
val func = (a:Int,b:Int)=>{a+b}
//高阶函数
val func2 = (a:Int,func:(Int,Int)=>Int)=>{func(a,a)}
}
//高阶函数
def add(x:Int,func:(Int,Int)=>Int) = func(x,x)
}
高阶函数简化:
- 直接传递函数的值
- 省略函数的参数
- 如果函数的参数只有一个,()可以省略
object test11 {
def main(args: Array[String]): Unit = {
//直接传递函数的值
add(10,(a:Int,b:Int)=>{a+b})
//省略函数的参数类型
add(10,(a,b)=>a+b)
//如果函数的参数类型只有一个,()可以省略
add2(10,a=>a*2)
//如果函数的参数在函数体中只使用了一次,那么可以用_进行代替
add2(10,_*2)
}
//高阶函数
def add(x:Int,func:(Int,Int)=>Int) = func(x,x)
def add2(x:Int,func:(Int)=>Int)=func(x)
}
- 如果函数的参数在函数体中只使用了一次,那么可以用_进行代替
注意:
//1、参数的在函数体中使用顺序如果与参数定义顺序不一致,此时不能用_代替:
val func = (x:Int,y:Int) => y-x
m1(10,20,(x,y) => y-x) //不能写成m1(10,20,_-_)
//2、如果函数只有一个参数,并且在函数体中是直接将参数返回,不做其他任何操作,此时不能用_代替
def m2(msg:String,func: String=>String) = {..}
m2("hello",(x:String)=>x) //不能写成m2("hello",_)
//3、如果函数体中有(),函数的参数在()中以表达式的方法存在,此时不能用_代替
def m3(x:Int,func: (Int)=>Int) = {..}
m3(10,(x:Int)=>(x+1)*10) 不能写成m2(10,(_+1)*10)
练习一下:
/*
Array[String]("hello","word","scala","python")
需求: 数组中的每个元素进行操作,操作规则由外部决定,生成的结果是
比如获取每个元素的长度:Array[Int](5,4,5,6)
*/
object test12 {
def main(args: Array[String]): Unit = {
val a1 = Array[String]("hello","word","scala","python")
val func = (str:String)=>{str.length}
val arr = StringLength(a1, func)
for(i<-arr){
println(i)
}
}
def StringLength(a1:Array[String],func:(String)=>Int)={
for(i<-a1)yield{
func(i)
}
}
}
/*
Array[Int](2,4,7,1,9)
需求: 对数组中的所有的元素进行统计,统计规则由外部决定,生成的结果是
比如需要统计总和:23
*/
object test13 {
def main(args: Array[String]): Unit = {
val a1 = Array[Int](2,4,7,1,9)
val func = (x:Int,y:Int)=>{x*y}
println(add(a1,func))
}
def add(a1:Array[Int],func:(Int,Int)=>Int)={
//取出第一个元素
var first = a1(0)
//从第二元素开始遍历
for(i <- 1 until a1.length){
first = func(first,a1(i))
}
first
}
}
/*
Array[Int](2,4,6,1,3,7)
需求: 根据指定的规则过滤出符合要求的数据,生成的结果是
比如只需要偶数的数据:Array[Int](2,4,6)
*/
object test14 {
def main(args: Array[String]): Unit = {
val a1 = Array[Int](2,4,6,1,3,7)
val func = (x:Int)=>{x%2==0}
val res = even(a1,func)
for(i<-res){
println(i)
}
}
def even(a1:Array[Int],func:(Int)=>Boolean)={
//for循环+守卫
for(i<-a1 if func(i))yield{
i
}
}
}
/*
Array[String]("zhangsan 20 5000","lisi 30 3000","zhaoliu 18 6000")
需求: 根据指定的规则获取最大的数据,生成的结果是
比如根据年龄获取最大的人:lisi 30 3000
*/
object test15 {
def main(args: Array[String]): Unit = {
val a1 = Array[String]("zhangsan 20 5000","lisi 30 3000","zhaoliu 18 6000")
val func = (str:String)=>{
val f:Array[String]=str.split(" ")
f(2).toInt
}
println(max(a1, func))
}
def max(a1:Array[String],func:(String)=>Int)={
var tep:String = null
for(i<- 1 until(a1.length)){
if(func(a1(i-1))>func(a1(i))){
tep=a1(i-1)
}else{
tep=a1(i)
}
}
tep
}
}
import java.util
/*
Array[String]("zhangsan 男 深圳","lisi 男 北京","zhaoliu 男 深圳","韩梅梅 女 北京")
需求:根据指定的规则对数据进行分组,生成的结果是
比如根据性别分组:
Map[男:Array[String]("zhangsan 男 深圳","lisi 男 北京","zhaoliu 男 深圳"),
女:Array[String]("韩梅梅 女 北京")]
*/
object test16 {
def main(args: Array[String]): Unit = {
val a1 = Array[String]("zhangsan 男 深圳","lisi 男 北京","zhaoliu 男 深圳","韩梅梅 女 北京")
val func = (str:String)=>{
str.split(" ")(2)
}
println(group(a1, func))
}
def group(a1:Array[String],func:(String)=>String)={
//装载结果的容器
var m = new util.HashMap[String,util.List[String]]
for(i<-a1){
//通过func函数获取key
var k = func(i)
//判断key值在map中是否已经存在,若存在则直接将元素添加到对应List中即可,
// 若不存在则先创建List,再把key、value放进map中
if(m.containsKey(k)){
val arr = m.get(k)
arr.add(i)
}else{
val list = new util.ArrayList[String]()
list.add(i)
m.put(k,list)
}
}
m
}
}
5.匿名函数*
概念:就是没有名字的函数
object test17 {
def main(args: Array[String]): Unit = {
//这里的x=>x*2就是隐名函数
println(add(10, x => x * 2))
}
def add(x:Int,func:(Int)=>Int)=func(x)
}
方法就是函数,函数也是对象
object test17 {
def main(args: Array[String]): Unit = {
//方法也是函数,将方法作为参数传入
println(m1(10, 10, add))
}
def m1(x:Int,y:Int,func:(Int,Int)=>Int)=func(x,y)
def add(a:Int,b:Int)={a+b}
}
6.函数柯里化&闭包*
柯里化:有多个参数列表的方法称为柯里化
object test18 {
def main(args: Array[String]): Unit = {
//得到一个函数
val f1 = add(10)
println(f1(20))
//柯里化演变
println(add(10)(20))
}
def add(x:Int)={
val func = (a:Int)=>{
a+x
}
func
}
}
输出结果:
30
30
object test18 {
def main(args: Array[String]): Unit = {
println(add(10)(20))
}
def add(x:Int)(y:Int)={x+y}
}
闭包:使用了不属于自身的变量的函数称之为闭包
object test18 {
def main(args: Array[String]): Unit = {
val y:Int = 10
//闭包函数,使用了不属于函数本身的变量y,y是函数外部变量
val func = (x:Int)=>{x+y}
println(func(2))
}
}
7.递归
定义:一个函数/方法在函数/方法体内又调用了本身
注意:
1、必须要有跳出的逻辑
2、方法调用自身时,传递的参数应该有规律
3、Scala中的递归必须声明函数返回值类型
object test19 {
def main(args: Array[String]): Unit = {
println(test(5))
}
//计算x的阶层
def test(x:Int):Int={
if(x==1){
1
}else {
x*test(x-1)
}
}
}
8.控制抽象
概念:由 =>返回值类型 表示的就是一个控制抽象,控制抽象其实就是块表达式;控制抽象的返回值就是块表达式的结果
object test20 {
def main(args: Array[String]): Unit = {
m1({
println("+++++++")
"hello world"})
}
def m1(func: =>String): Unit ={
//控制抽象可以当做函数来调用,但是在调用的时候不能带上()
func
}
}
9.惰性取值
定义:当函数返回值被声明为lazy时,函数的执行将被推迟,直到首次对此取值,该函数才会执行,这样的函数称为惰性函数。
注意:lazy不能修饰var定义的变量
object test21 {
def main(args: Array[String]): Unit = {
val a = 10
println(a)
lazy val b = 12
println("=================")
println("=================")
println(b)
}
}
六、面向对象
1.定义类
创建类:
calss 类名{
属性
方法
}
创建对象:
注意:如果不需要传入参数,则()可以省略
val person = new Person()
2.定义属性及方法
属性
语法:[访问修饰符] 类型 属性名 = 初始值
注意:在class中var标识的属性可以通过_赋予初始值,用_赋予初始值的时候必须指定属性的类型
方法
def hello(msg:String) =println(s"hello ${msg}")
example:
object test22 {
class Person{
val name = "yilei"
var age = 20
var sex:String = _
def getAdress()="深圳"
}
def main(args: Array[String]): Unit = {
val person = new Person
println(person.name)
person.age=30
println(person.age)
println(person.getAdress())
}
}
输出结果:
yilei
30
深圳
3.构造器
分两种:
1.主构造器:在类名后通过: ( [访问修饰符] val/var/默认不写 属性名:属性类型 [=默认值])表示
注意:主构造器中val/var标识的非private的参数就是公有的属性,外部与内部都可以使用
主构造器中不写val/var标识的属性相当于是private修饰的属性,只能在class内部使用
2.辅助构造器
注意:辅助构造器必须定义在class里面
定义语法:修饰符 def this(参数名:参数类型,…){
//方法第一行必须调用主构造器或者是其他的辅助构造器
this(…)
}
4.BeanProperty注解*
作用:java中很多API都需要get/set方法,scala中为了兼容java,提供了一个注解@BeanProperty注解,能够自动的生成set/get方法
注意:@BeanProperty只能用在非private修饰的属性上
object test23 {
class Person{
@BeanProperty
var name = "yilei"
//private修饰的属性,不能使用BeanProperty
private val age = 10
}
def main(args: Array[String]): Unit = {
val person = new Person
//修改name的值
person.setName("xiaoming")
//获取name的值并输出
println(person.getName)
}
}
5.继承
通过extends关键字实现继承关系
是否所有类都可以继承?
final修饰的类不能被继承
是否父类所有的属性和方法都可以被继承?
private修饰的属性与方法不可以被继承
是否父类所有的属性与方法都可以被重写?
var/final标识的属性不能被重写
7.包的管理
Java中对包的使用:
1、声明包:
a、语法:package 包名
b、声明包的时候必须在源文件第一行
2、导入包:
a、语法: import 包名
b、导入包必须在class外面,一般和package声明在一起
scala中对于包的使用:
1、声明包:
a、语法: package 包名
b、语法: package 包名{…}
2、导入包
scala中可以在任何地方导入包,导入包之后,包有作用域的问题:子作用域可以使用父作用域的包,父作用域不能使用在子作用域中导入的包
a、导入包中所有类:import 包名._
b、导入包中某个类: import 包名.类名
c、导入包中某几个类:import 包名.{类名1,类名2}
d、导入包中的类,并给类起别名[后续在创建类的时候可以通过别名来创建]:import 包名.{类名1=>别名}
e、导入包中除开某些类的所有类:import 包名.{排除的类名=>,}
3、包对象:
a、语法: package object 包名
包对象中非private修饰的属性与方法/函数可以在包中任何地方进行使用
8.抽象属性及抽象方法
* java中:
* 通过abstract关键字标识class是抽象类。
* 通过abstract关键字标识的方法是抽象方法。
* 子类继承抽象类之后,如果子类不是抽象类必须实现抽象方法
* scala中:
* 通过abstract关键字标识class是抽象类
* 抽象类中即可以定义抽象属性与抽象方法也可以定义具体属性与具体方法
* 抽象属性: 没有赋予初始值的属性称为抽象属性,抽象属性必须定义属性类型
* 抽象方法: 没有写方法体的方法称之为抽象方法,抽象方法必须定义返回值类型,如果不定义返回值类型,默认就是Unit
* 子类继承抽象类之后,如果子类不是抽象类必须实现抽象属性和抽象方法
9.单例模式*
单例对象: 只有一个对象
* java中单例模式需要将构造方法私有,提供公有的static的获取对象的方法
scala中没有static关键字,但是scala的object中所有的属性和方法都是类似java static修饰的
* scala 中object就是单例对象
object test24 {
def main(args: Array[String]): Unit = {
val obj1 = test24
val obj2 = test24
println(obj1)
println(obj2)
}
}
输出结果:
com.yilei.test24$@1b40d5f0
com.yilei.test24$@1b40d5f0
10.伴生类与伴生对象
* 伴生类与伴生对象:
* 1、class和object必须同名
* 2、class与object必须在同一个.scala文件中
* 伴生类与伴生对象的特性:
* 伴生类与伴生对象可以互相访问对方private修饰的属性和方法
*
* apply方法必须定义在伴生对象中,apply方法是用来简化伴生类的对象的创建
11.特质(trait)
解决单继承的问题,特质类似Java中的接口
* trait的基本语法: trait 特质名
* scala的trait中既可以定义抽象属性也可以定义具体属性
* 既可以定义抽象方法也可以定义具体方法
* scala中是单继承多实现的模式,所以只能继承一个class但是可以实现多个特质
* scala实现多个特质:
* 1、子类不需要继承class,此时实现第一个特质使用extends关键字,其他的特质都是使用with关键字
* 2、子类需要继承class,此时extends关键字用来继承class,特质的实现使用with关键字
特质混入:
- 在某些情况下可能只想让某些对象拥有特质的属性和方法
- 特质混入的方式就可以让某些对象拥有特质的属性和方法,而不是class所有的对象都拥有特质的属性和方法
- 特质混入语法: new 类名(…) with 特质名
scala可以实现多个特质:
- scala可以实现多个特质,如果这多个特质中有同名方法并且参数列表也一样,那么此时子类继承这多个特质之后调用方法时会报错
- 解决方案:
-
1、在子类中重写同名方法,如果在重新的同名方法中调用父类的同名方法,实际上调用的是按照继承顺序中最后一个特质的同名方法
-
2、将同名方法抽取到公有的特质中,子特质重写方法,子类再重写。如果子特质中有使用super调用父类的同名方法,最终的执行结果是先执行子类,再按照继承顺序从右向左开始执行,最终才会执行公有特质的同名方法
12.自类型(self)
语法:在trait中通过 this:指定类型
自类型表示子类继承该trait的时候必须同时继承/实现指定类型
场景:在协同开发时,我们继承其他同事写的trait时,就知道要实现哪些类了
13.类型检查与类型转换*
scala中判断对象是否属于某个类型:对象.isInstanceOf[类型]
scala中将对象转换成某个类型:对象.asInstanceOf[类型]
scala中获取对象的class形式:对象.getClass()
scala中获取类的class形式:classOf[类名]
七、集合*
1.集合简介
Scala的集合分为三大类:序列Seq、集合Set、映射Map
对于几乎所有集合类,scala都同时提供了可变与不可变版本,分别位于两个包内:
- 不可变集合:sacla.collection.immutable
- 可变集合:scala.collection.mutable
2.数组*
2.0 集合方法的区别
- 加减号个数的区别
- 一个+/- :添加/删除单个元素
- 两个+/- :添加/删除一个集合中的所有元素
- 冒号在前与在后以及不带冒号的区别
- 冒号在前:将元素添加到最后边
- 冒号在后:将元素添加到最前边
- 不带冒号:将元素添加到最后边,等同冒号在前
- 带=与不带=的区别
- 带=号:修改集合本身,只有可变集合才有
- 不带=号:生成一个新的集合,原来的集合不变
2.1 创建不可变数组
创建方式:
- new Array [元素的类型] (数组的长度)
- Array [元素的类型] (初始元素,…)
object ImmutableArray {
def main(args: Array[String]): Unit = {
val arr1 = new Array[Int](5)
val arr2 = Array[Int](1,2,3,4,5)
println(arr1.toBuffer)
println(arr2.toBuffer)
}
}
执行结果:
ArrayBuffer(0, 0, 0, 0, 0)
ArrayBuffer(1, 2, 3, 4, 5)
对数据进行增/改/查操作【注:增加元素都是生成一个新的数组】
object ImmutableArray {
def main(args: Array[String]): Unit = {
val arr1 = new Array[Int](5)
val arr2 = Array[Int](1,2,3,4,5)
println(arr1.toBuffer)
println(arr2.toBuffer)
//添加一个元素,生成一个新的集合
val arr3 = arr2.+:(10)
println(arr3.toBuffer)
//添加一个集合中的所有元素,生成一个新的集合
val arr4 = arr2.++:(Array[Int](100,200))
println(arr4.toBuffer)
//获取指定角标的元素
println(arr4(2))
//修改元素
arr4(2)=12
println(arr4.toBuffer)
//遍历
for(i<-arr4){
print(i +"\t")
}
println()
//不可变数组转可变数组
val arr5 = arr4.toBuffer
arr5.+=:(123)
println(arr5)
}
}
执行结果:
ArrayBuffer(0, 0, 0, 0, 0)
ArrayBuffer(1, 2, 3, 4, 5)
ArrayBuffer(10, 1, 2, 3, 4, 5)
ArrayBuffer(100, 200, 1, 2, 3, 4, 5)
1
ArrayBuffer(100, 200, 12, 2, 3, 4, 5)
100 200 12 2 3 4 5
ArrayBuffer(123, 100, 200, 12, 2, 3, 4, 5)
2.2 创建可变数组
创建方式:
- new ArrayBuffer [元素的类型] ()
- ArrayBuffer [元素的类型] (初始元素,…)
添加元素:
object MutableArray {
def main(args: Array[String]): Unit = {
val arr1 = new ArrayBuffer[Int](5)
val arr2 = ArrayBuffer[Int](9,8,7,6,5)
//添加单个元素
//改变集合本身
val arr3 = arr2.+=(10)
println(arr3)
println(arr2.eq(arr3))
//重新生成集合
val arr4 = arr2.+:(11)
println(arr4)
//添加数组中的所有数据
//改变集合本身
val arr5 = arr2.++=(Array[Int](12,13,14))
println(arr2.eq(arr5))
//生成新的集合
val arr6 = arr2.++:(Array[Int](15,16))
println(arr6)
}
}
执行结果:
ArrayBuffer(9, 8, 7, 6, 5, 10)
true
ArrayBuffer(11, 9, 8, 7, 6, 5, 10)
true
ArrayBuffer(15, 16, 9, 8, 7, 6, 5, 10, 12, 13, 14)
删除元素:
object MutableArray {
def main(args: Array[String]): Unit = {
val arr2 = ArrayBuffer[Int](9,8,7,6,5,9)
println(arr2)
//删除单个元素,若存在相同元素则删除排在前面的一个
arr2.-=(9)
println(arr2)
val arr3 = arr2.-(10)
println(arr3)
//删除一个集合的所有的元素
arr2.--=(Array(5,6))
println(arr2)
val arr4 = arr2.--(Array(9,8))
println(arr4)
}
}
执行结果:
ArrayBuffer(9, 8, 7, 6, 5, 9)
ArrayBuffer(8, 7, 6, 5, 9)
ArrayBuffer(8, 7, 6, 5, 9)
ArrayBuffer(8, 7, 9)
ArrayBuffer(7)
获取/修改元素、数组转换、多维数组
object MutableArray {
def main(args: Array[String]): Unit = {
val arr1 = new ArrayBuffer[Int](5)
val arr2 = ArrayBuffer[Int](9,8,7,6,5)
//获取元素
println(arr2(2))
//修改元素
arr2(2)=100
println(arr2)
//可变数组转不可变数组
val arr3 = arr2.toArray
//多维数组
//两行两列
val arr4 = Array.ofDim[Int](2,2)
println(arr4.length)
println(arr4(0).length)
}
}
执行结果:
7
ArrayBuffer(9, 8, 100, 6, 5)
2
2
3.Seq集合(List)*
3.1 不可变List
创建方式:
- List [元素类型] (初始元素,…)
- 元素 :: 元素 :: … Nil/List
添加元素
:: 添加单个元素
::: 添加一个List的所有元素
添加元素:
object ImmutableList {
def main(args: Array[String]): Unit = {
val list = List[Int](1,2,3)
println(list)
//Nil的方式(Nil空集合)
val list2 = Nil
println(list2)
//添加单个元素
val list3 = list2.+:(2)
println(list3)
val list4 = list2.::(3)
println(list4)
//通常用这种方式
val list5 = 4::5:: Nil
println(list5)
//添加集合中的所有元素
val list6 = list2.++(List[Int](10,11))
println(list6)
val list7 = list2.++:(Array(13,14))
println(list7)
val list8 = list2 ::: List(100,200)
println(list8)
}
}
执行结果:
List(1, 2, 3)
List()
List(2)
List(3)
List(4, 5)
List(10, 11)
List(13, 14)
List(100, 200)
获取/修改数据、list转数组
注意:修改数据用updated,并且是生成了新的数组
object ImmutableList {
def main(args: Array[String]): Unit = {
//Nil的方式(Nil空集合)
val list2 = Nil
println(list2)
val list3 = list2 ::: List(100,200)
println(list3)
//获取数据
println(list3(1))
//修改数据
//这种方式不可行list3(1)=0
val list4 = list3.updated(1,0)
println(list3)
println(list4)
//list转数组
val arr = list3.toBuffer
println(arr)
}
}
执行结果:
List()
List(100, 200)
200
List(100, 200)
List(100, 0)
ArrayBuffer(100, 200)
3.2 可变List
创建方式:
- ListBuffer = ListBuffer [元素类型] (初始元素,…)
添加 /删除元素:
object MutableList {
def main(args: Array[String]): Unit = {
val list = ListBuffer[Int](1,3,5,7,9)
//添加单个元素
val list1 = list.:+(10)
println(list)
println(list1)
list.+=(11)
println(list)
//添加某个集合中的所有元素
val list2 = list.++:(Array(100,200))
println(list2)
list.++=(Array(300,400))
println(list)
//删除单个元素
val list3 = list.-(1)
println(list3)
list.-=(400)
println(list)
//批量删除元素
val list4 = list.--(Array(1,3))
println(list4)
list.--=(Array(5,7))
println(list)
list.remove(300)
println(list)
}
}
执行结果:
ListBuffer(1, 3, 5, 7, 9)
ListBuffer(1, 3, 5, 7, 9, 10)
ListBuffer(1, 3, 5, 7, 9, 11)
ListBuffer(100, 200, 1, 3, 5, 7, 9, 11)
ListBuffer(1, 3, 5, 7, 9, 11, 300, 400)
ListBuffer(3, 5, 7, 9, 11, 300, 400)
ListBuffer(1, 3, 5, 7, 9, 11, 300)
ListBuffer(5, 7, 9, 11, 300)
ListBuffer(1, 3, 9, 11, 300)
ListBuffer(1, 3, 9, 11)
修改 / 获取元素
object MutableList {
def main(args: Array[String]): Unit = {
val list = ListBuffer[Int](1,3,5,7,9)
//修改元素
list(0)=100
println(list)
list.update(1,200)
println(list)
//获取元素
println(list(2))
}
}
执行结果:
ListBuffer(100, 3, 5, 7, 9)
ListBuffer(100, 200, 5, 7, 9)
5
修改 / 获取元素
object MutableList {
def main(args: Array[String]): Unit = {
val list = ListBuffer[Int](1,3,5,7,9)
//修改元素
//直接修改,不会生成新的List
list(0)=100
println(list)
list.update(1,200)
//修改并生成新的List
val list1 = list.updated(2,1000)
println(list)
println(list1)
//获取元素
println(list(2))
}
}
执行结果:
ListBuffer(100, 3, 5, 7, 9)
ListBuffer(100, 200, 5, 7, 9)
ListBuffer(100, 200, 1000, 7, 9)
5
4.Set集合
特点:无序,不重复
4.1 不可变Set
创建方式:
- Set [元素类型] (初始元素,…)
object ImmutableSet {
def main(args: Array[String]): Unit = {
val set = Set[Int](1,2,3,4)
//添加元素
val set1 = set.+(10)
println(set1)
val set2 = set.++(Array(11,12))
println(set2)
//删除元素
val set3 = set.-(1)
println(set3)
val set4 = set.--(Array(2,3))
println(set4)
}
}
执行结果:
Set(10, 1, 2, 3, 4)
Set(1, 2, 12, 3, 11, 4)
Set(2, 3, 4)
Set(1, 4)
4.2 可变Set
创建方式:
- mutable.set [元素的类型] (初始元素,…)
object MutableSet {
def main(args: Array[String]): Unit = {
val set = mutable.Set[Int](1,2,3,4)
//添加元素
val set1 = set.+(10)
println(set1)
val set2 = set.++(Array(11,12,13))
println(set2)
set.+=(100)
set.++=(Array(200,300))
println(set)
//删除元素
val set3 = set.-(1)
println(set3)
val set4 = set.--(Array(2,3))
println(set4)
set.-=(100)
set.--=(Array(200,300))
println(set)
//更新元素,ture表示10如果set中没有这个元素则添加
//false表示10如果set中有则进行删除
set.update(10,true)
println(set)
}
}
执行结果:
Set(1, 2, 3, 10, 4)
Set(12, 1, 13, 2, 3, 4, 11)
Set(1, 300, 100, 2, 3, 4, 200)
Set(300, 100, 2, 3, 4, 200)
Set(1, 300, 100, 4, 200)
Set(1, 2, 3, 4)
Set(1, 2, 3, 10, 4)
5.元组tuple*
创建方式:
- 通过()创建元组:(初始元素,…)
- 如果是创建二元元组,可通过K-V创建
- 元组一旦创建,元组的长度和元素都不可变
- 获取元素:元组变量名._角标【元组角标从1开始】
- 元组最多只能存储22个元素
创建实操:
class Tuple {
def main(args: Array[String]): Unit = {
//通过()创建
val t1 = ("yieli",20,"beijing")
//通过K-V创建二元元组
val t2 = "yilei"-> 20
//获取元素
val str = t1._1
val in:Int= t1._2
println(str)
}
}
应用场景
object Tuple1 {
def main(args: Array[String]): Unit = {
val list = List[(String,Int,String)](
("bai",10,"男"),
("hong",20,"女"),
("hei",10,"男")
)
//获取姓名
for(element<-list){
println(element._1)
}
println("======================================")
val list2 = List[(String,(String,(String,Int,String)))](
("北京",("G1314",("10点10分开",500,"14点10到"))),
("深圳",("G980",("10点21分开",400,"12点10到"))),
("上海",("G1298",("10点31分开",480,"13点10到")))
)
//或取到三个城市的票价
for(element<-list2){
println(element._2._2._2)
}
}
}
输出结果:
bai
hong
hei
======================================
500
400
480
6.Map集合*
Scala中不可变的Map是有序的,可变的Map是无序的
6.1 不可变Map
创建方式:
- Map[K的类型,v的类型] ((K,V),(K,V),(K,V),…)
- Map[K的类型,v的类型] ((K->V),(K->V),(K->V),…)
创建及添加元素
object ImmutableMap {
def main(args: Array[String]): Unit = {
//创建Map
val map = Map[String,Int](("bai",10),("hong",20),("hei",30))
println(map)
val map2 = Map[String,Int]("bai" -> 10,"hong"->20,"hei"->30)
println(map2)
//添加元素
val map3 = map2.+("zi"->40)
val map4 = map2.+(("huang",20))
println(map3)
println(map4)
val map5 = map2.++(Map(("feng"->24),("qing",26)))
println(map5)
val map6 = map2.++:(List(("huang",12)))
println(map6)
}
}
输出结果:
Map(bai -> 10, hong -> 20, hei -> 30)
Map(bai -> 10, hong -> 20, hei -> 30)
Map(bai -> 10, hong -> 20, hei -> 30, zi -> 40)
Map(bai -> 10, hong -> 20, hei -> 30, huang -> 20)
Map(feng -> 24, hei -> 30, qing -> 26, bai -> 10, hong -> 20)
Map(huang -> 12, bai -> 10, hong -> 20, hei -> 30)
修改及取值
object ImmutableMap {
def main(args: Array[String]): Unit = {
//创建Map
val map = Map[String,Int](("bai",10),("hong",20),("hei",30))
println(map)
val map2 = Map[String,Int]("bai" -> 10,"hong"->20,"hei"->30)
println(map2)
//添加元素
val map3 = map2.+("zi"->40)
val map4 = map2.+(("huang",20))
println(map3)
println(map4)
val map5 = map2.++(Map(("feng"->24),("qing",26)))
println(map5)
val map6 = map2.++:(List(("huang",12)))
println(map6)
//根据key获取value值
println(map2.getOrElse("bai", ""))
println("====================")
//获取所有key
//获取到key的迭代器
val keys = map2.keys
//遍历
for(key<-keys){
println(key)
}
println("====================")
//获取所有的value值
val values = map2.values
for(value<-values){
println(value)
}
println("====================")
//直接遍历Map所有元素
for(element<-map){
println(element._1,element._2)
}
println("====================")
//修改元素
val map7 = map.updated("hong","200")
println(map7)
println(map)
}
}
输出结果:
Map(bai -> 10, hong -> 20, hei -> 30)
Map(bai -> 10, hong -> 20, hei -> 30)
Map(bai -> 10, hong -> 20, hei -> 30, zi -> 40)
Map(bai -> 10, hong -> 20, hei -> 30, huang -> 20)
Map(feng -> 24, hei -> 30, qing -> 26, bai -> 10, hong -> 20)
Map(huang -> 12, bai -> 10, hong -> 20, hei -> 30)
10
====================
bai
hong
hei
====================
10
20
30
====================
(bai,10)
(hong,20)
(hei,30)
====================
Map(bai -> 10, hong -> 200, hei -> 30)
Map(bai -> 10, hong -> 20, hei -> 30)
6.2 可变Map
创建方式:
- mutable.Map [String,Int] ((“bai”,20),(“hong”,30)
- mutable.Map [String,Int] (“bai->20”,“hong->30”)
案例来一波:
object MutableMap {
def main(args: Array[String]): Unit = {
val map = mutable.Map[String,Int]("hong"->20,"bai"->30)
val map1 = mutable.Map[String,Int](("hong",20),("bai",20))
//添加元素
val map2 = map.+("huang"->30)
map.+=(("zi",40))
println(map)
println(map2)
val map3 = map.++(Map("hei"->34))
map.++=(Map(("lan",20)))
println(map)
println(map3)
//删除元素
val map4 =map.-("zi")
map.-=("bai")
println(map)
println(map4)
val map5 = map.--(List("lan"))
map.--=(List("lan"))
println(map)
println(map5)
map.remove("hong")
println(map)
println("---------------")
//修改元素
map.+=("zi"->50)
println(map)
map.update("zi",20)
val map10 = map.updated("zi",40)
println(map)
println(map10)
println("---------------")
//查看元素
val value = map.getOrElse("zi","")
println(value)
val value1 = map.getOrElse("zi1","lihaile")
println(value1)
println("---------------")
//获取所有的key
for(key<-map1.keys){
println(key)
}s
println("---------------")
//获取所有的value
for(value<-map1.values){
println(value)
}
println("---------------")
//遍历所有元素
for(element<-map2){
println(element)
}
}
}
输出结果:
Map(bai -> 30, zi -> 40, hong -> 20)
Map(bai -> 30, huang -> 30, hong -> 20)
Map(lan -> 20, bai -> 30, zi -> 40, hong -> 20)
Map(bai -> 30, zi -> 40, hei -> 34, hong -> 20)
Map(lan -> 20, zi -> 40, hong -> 20)
Map(lan -> 20, bai -> 30, hong -> 20)
Map(zi -> 40, hong -> 20)
Map(zi -> 40, hong -> 20)
Map(zi -> 40)
---------------
Map(zi -> 50)
Map(zi -> 20)
Map(zi -> 40)
---------------
50
lihaile
---------------
bai
hong
---------------
20
20
---------------
(bai,30)
(huang,30)
(hong,20)
7. 集合常用函数*
7.1 基本属性
基本操作:
object BasicOperator {
def main(args: Array[String]): Unit = {
val list = ListBuffer[Int](9,11,4,1,20,3,4)
//获取集合长度
println("长度:"+list.length)
//获取集合大小
println("长度:"+list.size)
println("========遍历=========")
//循环遍历
for(element<-list){
println(element)
}
println("========迭代器遍历=========")
//迭代器
val iterator = list.toIterator
for(element<-iterator){
println(element)
}
println("========生成字符串=========")
//生成字符串
val str = list.mkString("-")
println(str)
println("========是否包含=========")
//是否包含
println(list.contains(9))
}
}
执行结果:
长度:7
长度:7
========遍历=========
9
11
4
1
20
3
4
========迭代器遍历=========
9
11
4
1
20
3
4
========生成字符串=========
9-11-4-1-20-3-4
========是否包含=========
true
7.2 衍生集合
基本操作:
object DeriveCollection {
def main(args: Array[String]): Unit = {
val list = List(2,4,6,8,10,4)
println("=========去重==========")
//去重
val list2 = list.distinct
println(list2)
println("=========删除元素==========")
//删除元素前多少个元素
val list3 = list.drop(2)
println(list3)
//删除后多少个元素
val list4 = list.dropRight(1)
println(list4)
println("=========获取几个元素==========")
//获取第一个元素
val list5 = list.head
println(list5)
//获取前多少个元素
val list50 = list.take(3)
println(list50)
//获取最后一个元素
val list6 = list.last
println(list6)
//获取最后多少个元素
val list60 = list.takeRight(3)
println(list60)
//获取除开最后一个元素的所有元素
val list7 = list.init
println(list7)
//获取除开第一个元素的所有元素
val list70 = list.tail
println(list70)
println("=========集合反转==========")
//集合反转
val list8 = list.reverse
println(list8)
println("=========截取字串==========")
//获取子集合,(0,2)表示从索引位置0到索引位置2,左闭右开
val list9 = list.slice(0,2)
println(list9)
println("=========滑窗==========")
//滑窗 size:窗口大小 step:滑动长度
val list10 = list.sliding(2,1)
for(element<-list10){
println(element)
}
val list11 = list.sliding(2,2)
println(list11)
println("=========拉链==========")
//拉链
val names = List("hong","bai","zi","hei")
val ages = List(20,30,10)
val persons = names.zip(ages)
println(persons)
//反拉链
val list12 = persons.unzip
println(list12)
println("=========并/交/差集==========")
val list13 = List(1,2,3,4,5)
val list14 = List(3,4,5,6,7,8)
//并集,不去重
val list15 = list13.union(list14)
println(list15)
//交集,两个集合的相同部分
val list16 = list13.intersect(list14)
println(list16)
//差集:A.diff(B)则从A中取出B中没有的部分
val list17 = list13.diff(list14)
println(list17)
}
}
执行结果:
=========去重==========
List(2, 4, 6, 8, 10)
=========删除元素==========
List(6, 8, 10, 4)
List(2, 4, 6, 8, 10)
=========获取几个元素==========
2
List(2, 4, 6)
4
List(8, 10, 4)
List(2, 4, 6, 8, 10)
List(4, 6, 8, 10, 4)
=========集合反转==========
List(4, 10, 8, 6, 4, 2)
=========截取字串==========
List(2, 4)
=========滑窗==========
List(2, 4)
List(4, 6)
List(6, 8)
List(8, 10)
List(10, 4)
<iterator>
=========拉链==========
List((hong,20), (bai,30), (zi,10))
(List(hong, bai, zi),List(20, 30, 10))
=========并/交/差集==========
List(1, 2, 3, 4, 5, 3, 4, 5, 6, 7, 8)
List(3, 4, 5)
List(1, 2)
7.3 集合初级函数
实操:
object CollectionLowFunction {
def main(args: Array[String]): Unit = {
val list = List(1,10,9,8,4,3,6)
println("========最大值/最小值/求和========")
//最大值
val list1 = list.max
println(list1)
//最小值
val list2 = list.min
println(list2)
//求和
val list3 = list.sum
println(list3)
println("========指定规则获取最大/小值========")
val list4 = List(("hong",20,5000),("bai",30,6000),("hei",35,7500))
//传入一个函数:func:(String,Int,Int)=>Int
val list5 = list4.maxBy(_._3)
println(list5)
//传入一个函数:func:(String,Int,Int)=>Int
val list6 = list4.minBy(_._2)
println(list6)
println("========指定规则排序========")
//按年龄进行排序(升序)
val list7 = list4.sortBy(_._2)
println(list7)
//按薪资降序排序
val list8 = list4.sortBy(_._3).reverse
println(list8)
//指定排序方式
//传入函数func:(Int,Int)=>Boolean
//val func = (x:Int,y:Int)=>x<y
val list9 = list.sortWith(_<_)
println(list9)
val list10 = list.sortWith(_>_)
println(list10)
}
}
执行结果:
========最大值/最小值/求和========
10
1
41
========指定规则获取最大/小值========
(hei,35,7500)
(hong,20,5000)
========指定规则排序========
List((hong,20,5000), (bai,30,6000), (hei,35,7500))
List((hei,35,7500), (bai,30,6000), (hong,20,5000))
List(1, 3, 4, 6, 8, 9, 10)
List(10, 9, 8, 6, 4, 3, 1)
7.4 集合高级函数
groupBy函数:
object test1 {
def main(args: Array[String]): Unit = {
val list = List(4,2,4,5,6,2,9)
println(list.groupBy(x => x % 2 == 0))
val list2 = List(("湖南","长沙","雨花区"),("湖南","长沙","芙蓉区"),("江西","南昌","东湖区"),("江西","南昌","红谷滩新区"),("广东","广州","天河"))
//需求按照省份及城市分组
//注意留意返回值类型
val list3 = list2.groupBy(x=>(x._1,x._2))
println(list3)
val list4 = list2.groupBy(x=>{
List(x._1,x._2)
})
println(list4)
}
}
输出结果:
Map(false -> List(5, 9), true -> List(4, 2, 4, 6, 2))
Map((广东,广州) -> List((广东,广州,天河)), (江西,南昌) -> List((江西,南昌,东湖区), (江西,南昌,红谷滩新区)), (湖南,长沙) -> List((湖南,长沙,雨花区), (湖南,长沙,芙蓉区)))
Map(List(湖南, 长沙) -> List((湖南,长沙,雨花区), (湖南,长沙,芙蓉区)), List(江西, 南昌) -> List((江西,南昌,东湖区), (江西,南昌,红谷滩新区)), List(广东, 广州) -> List((广东,广州,天河)))
map函数:
特点:map针对的是整个集合的每一个元素
场景:一对一
val list = List("hello","world","spark")
list.map(x=>x.length)
输出结果:
List(5,5,5)
filter函数:
特点:对集合中每一个函数进行操作,保留函数返回值为true的元素
val list = List(1,4,2,6,5,10)
list.filter(_%2==0)
输出结果:
List(4,2,6,10)
flatten函数:
特点:只能用于集合套集合(字符串底层就是集合)
场景:一对多
object test1 {
def main(args: Array[String]): Unit = {
val list = List("spark","spark")
println(list.flatten)
val list1 = List(
List("spark","spark"),
List("scala","scala")
)
println(list1.flatten)
}
}
输出结果:
List(s, p, a, r, k, s, p, a, r, k)
List(spark, spark, scala, scala)
flatMap函数
特点:针对集合中的每个一元素,相当于map+flatten
场景:一对多
object test1 {
def main(args: Array[String]): Unit = {
val list = List("spark kafka HBase","spark scala")
println(list.flatMap(_.split(" ")))
}
}
执行结果:
List(spark, kafka, HBase, spark, scala)
foreach函数:
特点:针对的是集合的每一元素,func:元素类型=>Unit
他与map的区别在于他没有返回值
object test1 {
def main(args: Array[String]): Unit = {
val list = List("spark","scala")
list.foreach(println(_))
}
}
执行代码:
spark
scala
reduce函数:
特点:针对集合的每一个元素,func: (集合元素类型,集合元素类型)=>集合元素类型
应用场景:一对多
object test1 {
def main(args: Array[String]): Unit = {
val list = List(4,2,4,5,6,2,3)
val list1 = list.reduce((agg,curr)=>{
curr-agg
})
println(list1)
/*
计算过程:
第一次计算时:agg=4,curr=2 2-4=-2
第二次计算时:agg=-2,curr=4 4-(-2)=6
*/
}
}
计算结果:
8
reduceRight函数:
特点:和reduce相似,只是他是从右边开始的
object test1 {
def main(args: Array[String]): Unit = {
val list = List(4,2,4,5,6,2,9)
val list1 = list.reduceRight((curr,agg)=>{
curr-agg
})
println(list1)
/*
计算过程:
第一次计算时:agg=9,curr=2 2-9=-7
第二次计算时:agg=-7,curr=6 6-(-7)=13
*/
}
}
执行结果:
14
fold函数:
函数签名:fold[A1 >: A] (z: A1)(op: (A1, A1) => A1): A1
特点:与reduce相似,只是他指定初始值fold(agg初始值)(func:(元素类型,元素类型)=>元素类型)
object test1 {
def main(args: Array[String]): Unit = {
val list = List(4,2,4,5,6,2,9)
val list1 = list.fold(10)((agg,curr)=>{curr-agg})
println(list1)
}
}
执行结果
4
foldLeft函数:
函数签名:foldLeft[B] (z: B)(@deprecatedName('f) op: (B, A) => B): B
注意与fold的区别,主要关注参数类型
foldRight函数:
函数签名:foldRight[B] (z: B)(op: (A, B) => B): B
同fold,只是从右边开始
object test1 {
def main(args: Array[String]): Unit = {
val list = List(4,2,4,5,6,2,9)
val list1 = list.foldRight(5)((curr,agg)=>{curr-agg})
println(list1)
}
}
执行结果
9
7.5 队列
不可变队列:
创建方式:Queue[元素类型] (初始元素,初始元素,…)
object ImmutableQueue {
def main(args: Array[String]): Unit = {
val queue = Queue[Int](1,2,3,4,9)
println(queue)
//添加元素
val queue1 = queue.+:(10)
println(queue1)
val queue2 = queue.:+(0)
println(queue2)
val queue3 = queue.++(List(100,200))
println(queue3)
val queue4 = queue.++:(List(1234))
println(queue4)
//enqueue方法添加是加在最后边
val enqueue = queue.enqueue(100)
println(enqueue)
//删除元素,删除先进来的元素
val dequeue = queue.dequeue
println(dequeue)
//根据角标获取元素
println(queue(0))
}
}
输出结果:
Queue(1, 2, 3, 4, 9)
Queue(10, 1, 2, 3, 4, 9)
Queue(1, 2, 3, 4, 9, 0)
Queue(1, 2, 3, 4, 9, 100, 200)
Queue(1234, 1, 2, 3, 4, 9)
Queue(1, 2, 3, 4, 9, 100)
(1,Queue(2, 3, 4, 9))
1
可变队列:
创建方式:mutable.Queue[元素类型] (初始元素,…)
object MutableQueue {
def main(args: Array[String]): Unit = {
val queue = mutable.Queue[Int](1,2,3,4,1)
println(queue)
//添加元素
val queue1 = queue.+:(9)
println(queue1)
val queue2 = queue.+=:(10)
println(queue2)
val queue3 = queue.++:(List(100,101))
println(queue3)
val queue4 = queue.++=(List(1000))
println(queue4)
queue.enqueue(10000)
println(queue)
//删除元素
val dequeue = queue.dequeue()
println(dequeue)
//获取元素
println(queue(1))
//修改元素
queue(0)=1234
println(queue)
}
}
执行结果:
Queue(1, 2, 3, 4, 1)
Queue(9, 1, 2, 3, 4, 1)
Queue(10, 1, 2, 3, 4, 1)
Queue(100, 101, 10, 1, 2, 3, 4, 1)
Queue(10, 1, 2, 3, 4, 1, 1000)
Queue(10, 1, 2, 3, 4, 1, 1000, 10000)
10
2
Queue(1234, 2, 3, 4, 1, 1000, 10000)
7.6 并行集合
object TestPar {
def main(args: Array[String]): Unit = {
val res1 = (0 to 5).map(x=>{Thread.currentThread.getName})
val res2 = (0 to 3).par.map(x=>{Thread.currentThread.getName})
println(res1)
println(res2)
}
}
执行结果:
Vector(main, main, main, main, main, main)
ParVector(scala-execution-context-global-12, scala-execution-context-global-12, scala-execution-context-global-13, scala-execution-context-global-13)