1、Scala的变量和数据类型
1、变量命名规范:
首位必须是字母或者_或者特殊符号,其他的字符必须是数字、字母、_、特殊符号
2、变量
1、定义: val/var 变量名:变量类型 = 值
2、val与var的区别:
val定义的变量不可用被重新赋值,类似java的final
var定义的变量可以被重新赋值
3、scala在定义变量的时候,可以省略变量类型,scala会自动推断
3、字符串定义
1、""包裹会得到一个字符串: val name = "zhangsan"
2、插值表达式[就是字符串的拼接]: s"hello ${变量名/表达式}"
3、三引号[三引号的字符串能够原样保持输入格式]: val sql = """select * from xx"""
4、字符串的一些方法: "xx %s".format("hello")
4、键盘输入:
1、控制台输入: StdIn.readLine()
2、读取文件: Source.fromFile(path,code)
5、数据类型:
Any:所有类的父类
AnyVal:值类型
Byte、Short、Int、Long、Float、Double、Boolean、Char
Unit: 有一个实例(),相当于java的void
StringOps: 对java的String的扩展
AnyRef:引用类型
String、java的class、scala的class、集合
Null: 有一个实例null。是所有引用类型的子类
后续如果使用null对引用类型赋初始值的时候,变量必须指定类型
Nothing:所有类的子类,一般是scala自己使用
6、数字与字符串的转换
1、数字转换成字符串:
1、通过toString方法: 1.toString
2、通过插值表达式: s"${1}"
2、字符串转数字: toXXX方法
7、数字与数字间的类型转换
1、低精度自动可以向高精度转换: Int->Long
2、高精度转低精度: toXXX方法
2、运算符
1、算符运算符
2、关系运算符
3、逻辑运算符
4、赋值运算符
5、位运算符
scala中没有三目运算符、没有++ 、--
3、流程控制
1、块表达式:
1、定义: {}包裹的代码块称之为块表达式
2、块表达式有返回值,返回值为{}中最后一行表达式的结果值
2、if-else
1、单if
2、if-else
3、if-else if-else
if-else有返回值,返回值为满足条件的一个分支的{}最后一行表达式的结果值
// 单个if
def testIf(): Unit ={
val number=30
var result=if (number%2==0){
number
}
println(result)
}
// if-else
def testIfElse(): Unit ={
var number=30
var result=if (number>60){
number-90
}else {
number*4
}
println(result)
}
//testIfElse()
// if-else if-else
def testIfElseIfElse(): Unit ={
val number =20
val result=if (number>10){
"10-30"
}else if (number>30){
"30-~"
}else{
"小于10"
}
println(result)
}
//testIfElseIfElse()
// 如果没有最后一行的话 即返回()
val number=90
val result=if (number>20){
if (number%3!=0){
number*2
}
}
println(result)
3、for循环
1、to方法: 会生成一个集合,集合的范围是左右闭合
1.to(10) => 1,2,3,4,5,6,7,8,9,10
2、until方法:会生成一个集合,集合的范围是左闭右开
1.until(10) => 1,2,3,4,5,6,7,8,9
3、方法调用的两种方式:
1、对象.方法名(参数,..)
2、对象 方法名 (参数,...)
如果参数只有一个,()可以省略
4、for循环
1、语法: for(变量 <- 数组/集合/表达式){...}
2、守卫:
for(变量 <- 数组/集合/表达式 if 布尔表达式){...}
守卫其实就是每次循环的时候对变量进行判断,如果满足条件才会执行循环体
3、嵌套for循环
for(变量 <- 数组/集合/表达式;变量 <- 数组/集合/表达式;..){...}
嵌套for循环再使用的时候每层循环都可以搭配守卫使用
4、引入变量
for(变量 <- 数组/集合/表达式;变量名=变量值;变量 <- 数组/集合/表达式;..){...}
5、步长
for(变量 <- 1 to 10 by 步长){...}
6、for返回值:
for(变量 <- 数组/集合/表达式) yield{...}
yield表达式会生成一个集合
// to 左右闭合
def ToTest(): Unit ={
for (i<-0 to 10){
println(i)
}
}
// until 左闭右开
def nutilTest(): Unit ={
for (number<-0 until 10){
println("*"*number)
}
}
// NutilTest()
//守卫:
def protectTest(): Unit ={
for (i<- 0 to (10,2) if (i%2==0)){
println(i)
}
}
//protectTest()
// 嵌套for循环
def forAndFor(): Unit ={
for (number<-1 until 10){
for(j <-1 to number) {
print(s"${j}*$number=${j * number}")
print("\t")
}
println()
}
}
// forAndFor()
def forAndFor2(): Unit ={
for (number<-1 until 10;j <-1 to number){
print(s"$j*$number=${number*j}\t")
if (j==number){
println()
}
}
}
//forAndFor2()
def forAndFor3(): Unit ={
for (i<-1 to 9 if (i%2==0);j<-1 to i ){
println(s"$i*$j=${i*j}\t")
}
}
forAndFor3()
// for循环有返回值
def forAndResult(): Unit ={
val result=for (i<- Range(0,10,2))yield {
println(i)
i
}
println(s"返回值$result")
}
//forAndResult()
/**
* Range和until一样,左闭右开
*/
for(i<- Range(0,10))print(i+"\t")
println()
for (i<- 0 to 10)print(i+"\t")
println()
for (i<-0 until 10)print(i+"\t")
}
4、while与do-while
scala中while与do-while的用法与java一样
while与do-while的区别:
while是先判断再执行
do-while是先执行再判断
/**
* while和do-while的用法和java的一样
* while 和 do while的区别
* while是先判断再循环
* do-while是先循环再判断
*/
object WhileAndDoWhile_Dome {
def main(args: Array[String]): Unit = {
val number=11
while (number<=10){
println("hello")
}
do {
println(number)
}while(number<=10)
}
}
5、break与continue
scala中没有break与continue关键字
scala实现break功能:
1、导包: import scala.util.control.Breaks._
2、通过breakable与break方法实现break功能
breakable({
for(i<- 1 to 10){
if(i==5) break()
println(...)
}
})
scala实现continue功能:
1、导包: import scala.util.control.Breaks._
2、通过breakable与break方法实现break功能
for(i<- 1 to 10){
breakable({
if(i==5) break()
println(...)
})
}
package com.zhijm.Day02
/**
* 控制对象
* Breaks:捕捉异常
* breakable是一个函数
* 参数列表中如果有多行逻辑,可以采用大括号代替
* scala支持将代码逻辑作为参数传递给函数使用
* 如果函数参数想要传递代码逻辑,那么类型声明的方式应该为:
* 参数名: =>返回值类型(unit)
* 因为参数类型中没有声明小括号,所以调用是也不能加小括号
*/
object $12_Breaks {
def main(args: Array[String]): Unit = {
//val number=10
//val number1=100
//func(println(number+number1))
func2("hello")(
{
println("scala")
}, {
"good"
}
)
}
def func(f: =>Unit)={
f
}
def func2(flag:String)(f: =>Unit,f1: =>String)={
println(flag)
f
f1
}
}
4、函数式编程
方法就是函数,函数也是对象
1、方法
1、语法: def 方法名(参数名:参数类型,...):返回值类型 = {方法体}
2、简化原则:
1、如果方法体中只有一行语句,{}可以省略
2、如果方法使用{}最后一行表达式作为方法的返回值,返回值类型可以省略
3、如果方法不需要参数,那么()可以省略
注意:
1、如果定义方法的时候,没有(),调用的时候也不能带上()
2、如果定义方法的时候有(),调用的时候()可有可无
3、()、=、{}不能同时省略
4、如果方法体中有return关键字,返回值类型必须定义
5、如果方法不需要返回值,=可以省略
=、{}不能同时省略
package com.zhijm.Day02
/**
* 方法定义语法:
* def 方法名(参数名:参数类型,...):返回值类型 = {方法体}
* 方法的调用: 方法名(参数值,..)
*
* 方法的简化原则:
* 1、如果方法的返回值是{}最后一行表达式的结果值,那么方法的返回值类型可以省略
* 如果方法体中带有return关键字,则必须定义返回值类型
* 2、如果方法体只有一行语句,{}可以省略
* 3、如果方法不需要参数,()可以省略
* 如果定义方法的时候没有加上(),在调用方法的时候也不能加上()
* 如果定义方法的时候加上(),在调用方法的时候可以加上(),也可以省略()
* 4、如果方法不需要返回值,=可以省略【=、{}不能同时省略】
*
*
*/
object $01_MethodDefined {
def main(args: Array[String]): Unit = {
var result=add(2,3)
println(result)
println("去掉返回值类型")
println(add1(2,3))
println("去掉返回值类型和{}")
println(add2(2,3))
println("方法没有参数列表,省略()")
// 声明方法的时候没有加(),那么调用的时候也不需要加()
// 如果声明方法的时候加上了(),那么调用方法的时候可以加()也可以不加
add3
add4()
println("方法没有返回值,那么可以省略=,但是=和{}不可以同时省略")
add5
}
// 方法的定义格式: def 方法名(参数名:参数类型,...):返回值类型={方法体}
def add(x:Int,y:Int):Int={
x+y
}
// =======================方法的简化===============================
// 1,如果方法的返回值是{}最后一行表达式的结果值,那么方法的返回值类型可以省略
// 但是如果方法体中带有return关键字,则必须定义返回值类型
def add1(x:Int,y:Int)={x+y}
// 因为null0可以代替任何的AnyRef,所以需要指定返回值类型
def getName(name:String,agr:String):String={
if (name==null) return null
agr
}
// 2 如果方法体中只有一段逻辑,也就是只有一行语句,方法体的{}可以省略
def add2(x:Int,j:Int)=x+j
// 3 如果方法没有参数列表,则()可以省略
// 如果定义方法的时候没有加上(),在调用方法的时候也不能加上()
// 如果定义方法的时候加上(),在调用方法的时候可以加上(),也可以省略()
def add3=println(99)
def add4()=println(2000)
// 4,如果方法没有返回值,那么=可以省略,但是=和{}不可以同时省略
def add5{println("good")}
}
2、函数
1、定义: val 函数名 = (参数名:参数类型,...) => {函数体}
函数只有一个简化原则:如果函数体中只有一行语句,{}可以省略
package com.zhijm.Day02
object $02_FunctionDefined {
/**
* 函数定义:
* val 函数名 = (参数名:参数类型,...) => {函数体}
* 在函数中不能使用return
* 函数必须先定义在调用
*
* 函数就是对象
* 方法与函数的区别:
* 1、方法是随着类的加载而加载,函数只有定义在类中的时候才会随着类的加载而加载,如果定义在方法里面,只有调用方法的时候才会加载
* 2、方法放在方法区中,函数放在堆中
*
* 方法转成函数: 方法名 _
* 函数调用的时候必须带上()
*
* 函数的简化原则: 如果函数体中只有一行语句,则{}可以省略
*/
def main(args: Array[String]): Unit = {
// 1 函数的调用,必须加上(),不加()只是函数对象不具有运行的功能
println(add(1,23))
// 函数必须先定义再调用
// add1() 报错,add1函数还没有声明
var add1=(i:Int,j:Int)=>{i+j}
// 随着类的加载而加载
printStr("zhangsan")
// 随着main方法的加载而加载
var printStr2=(name:String)=>{print(name)}
printStr2("礼拜")
println("方法可以转为函数")
def add2(x:Int,y:Int):Int={
x+y
}
// 这个是调用函数,并把结果赋值给addFun
var addFun=add2(2,3)
println(addFun)
// 把一个方法转为一个函数对象,需要用方法名 _进行转换
var fun=add2 _;
println(fun(2,4))
// 函数的简化
printStr3()
}
//1 函数的定义 val 函数名=(参数名:参数类型,..)=>{函数体}
val add=(i:Int,j:Int)=>{i+j}
// 2 函数声明在类中,会随着类的加载加载,如果声明在方法中会随着方法的调用而加载
val printStr=(name:String)=>println(name)
// 3 函数的简化原则:如果函数体只有一行语句,则可以省略{}
var printStr3=()=>println("scala")
}
3、方法与函数的区别:
1、方法存放在方法区,函数是对象,存放在堆中
2、方法可以先调用在定义,函数是必须先定义再调用
3、方法可以重载,函数不可用重载
4、方法转函数:
方法名 _
println("方法可以转为函数")
def add2(x:Int,y:Int):Int={
x+y
}
// 这个是调用函数,并把结果赋值给addFun
var addFun=add2(2,3)
println(addFun)
// 把一个方法转为一个函数对象,需要用方法名 _进行转换
var fun=add2 _;
println(fun(2,4))
5、方法的参数定义:
1、默认值: 在定义方法的时候,可以给参数赋予默认值,在调用的时候就可以不用传参
默认值参数要放在后面
2、带名参数: 如果方法在定义的时候,有默认值的参数没有放在最后面,那么在调用方法的时候传参就必须通过带名参数的形式指定将值传递给哪个参数
def m1(x:Int=0,y:Int) = {..}
m1(y=2)
3、可变参数: 参数个数不固定
def m1(x:Int,y:Int*)
可变参数不能与默认值、带名参数同时使用
可变参数必须放在参数列表的最后面
将数组的元素作为参数传递给可变参数,通过 数组名:_*的形式传递: m1(10,arr:_*)
package com.zhijm.Day02
import java.text.SimpleDateFormat
import java.util.{Calendar, Date}
import javafx.scene.chart.PieChart.Data
/**
* java中方法的参数:
* 1、类型 参数名
* 2、类型... 参数名
* scala中方法的参数
* 1、参数名 参数类型
* 2、默认值: 参数名 参数类型=值
* 3、可变参数: 参数名 参数类型*
* 可变参数不可以与默认值一起使用
* 可变参数必须放在最后面
*
* 方法在调用的时候,可以通过带名参数给指定的参数进行赋值
* 将数组/集合的所有元素放入可变参数中: 数组:_*
*/
object $03_MethodParam {
def main(args: Array[String]): Unit = {
// 有返回值和有参数
println(add(1, 3))
// ==============================默认参数=======================
// 有默认值的参数,不传值则用默认值
println(add1())
// 第一个参数就是赋值给第一参数
println(add1(1))
// 显示声明给那个参数赋值,需要把参数名写上
println(add1(y=2))
//=====================可变参数================================
// 可变参数 可以是0个或多个
println(add2())
// 也可以多个
println(add2(1, 2, 3))
// 传入任意类型的参数
printAny(1, "aa", Array[String]("a", "d"))
// 传入数组,:_* 代表把数组中每一个元素都传到可变变量中
printArray(Array[Int](1,2,3):_*)
readPath(getPath(4):_*)
}
// 有参数,有返回值->参数名:参数类型
def add(x:Int,y:Int)=x+y
// 有默认值的参数->参数名:参数类型=默认值
def add1(x:Int=0,y:Int=0)=x+y
//可变参数
def add2(x:Int*)=x.size
// 可变参数的后面不能有参数
def add3(x:Int,y:Int*)=y.sum+x
// 报错,默认参数和可变参数不能一起使用,因为调用方法的时候参数传值会有歧义
//def add4(x:Int=0,y:Int*)=y.sum+x
// 定义可变参数可以传入任意类型的参数 需要用到any
def printAny(x:Any*)=println(x.size)
// java中可变参数可以传入数组,scala中也可以 但是需要特定的格式 数组:_*
def printArray(x:Int*)=x.size
def getPath(day:Int)={
val prefix="/user/hive/warehouse/user_info/"
val format=new SimpleDateFormat("yyyyMMdd")
for (i<-1 to day)yield{
val date= new Date()
val calendar=Calendar.getInstance()
calendar.setTime(date)
calendar.add(Calendar.DAY_OF_YEAR,-i)
val str=format.format(calendar.getTime)
s"${prefix}${str}"
}
}
def readPath(path:String*)={
for(str<-path)println(str)
}
}
6、高阶函数
1、定义: 使用函数作为参数或者返回值的方法/函数
def m1(a:Int,b:Int,func: (Int,Int)=>Int) = {..}
m1(2,3,(x:Int,y:Int)=>x+y)
def m2(a:Int,func: (Int)=>Int) = {..}
m2(10,(x:Int)=>x*x)
2、高阶函数在传递函数的时候简写
1、函数的参数类型可以省略
m1(2,3,(x,y)=>x+y)
2、如果函数只有一个参数,()可以省略
m2(10,x=>x*x)
3、如果函数的参数在函数体中只使用了一次,可以用_代替
m1(2,3,_+_)
有两种情况不能用_代替:
1、如果函数只有一个参数,并且在函数体中没有做任何操作,直接将参数返回
m2(10,(x:Int)=>x)
m2(10,x=>x)
2、如果函数体中有(),并且函数的参数在函数体的()中,则参数不能用_代替
m2(10,(x:Int)=>(x+1)*10)
m2(10,x=>(x+1)*10)_
package com.zhijm.Day02
/**
* 高阶函数: 参数/返回是函数的方法/函数
* 高阶函数传参的简化:
* 1、传入的函数可以省略参数类型
* 2、如果函数只有一个参数,则()可以省略
* 3、如果函数的参数在函数体中,只使用了一次,则可以通过_代替,下面两种情况除外
* 1、如果函数参数只有一个,并且在函数体中直接返回参数本身,则参数不能用_代替
* 2、如果函数体中有(),而且函数的参数处于函数体的()中,则不能用_代替
*
*/
object $04_HightFunction {
def main(args: Array[String]): Unit = {
// 函数当参数
var func=(a:Int,b:Int)=>a+b
println(m1(12, 20, func))
val func2=m2((x:Int,y:Int)=>{x+y})
println(func2)
println(m3((i: Int) => i * 4))
// 函数当做返回值
println(m4()(3, 5))
println("@"*20)
// 函数当参数的时候进行简化
// 1 不简化
println(m5(7, 3, (a: Int, b: Int) => {
a + b
}))
// 1.1传入的函数可以省略参数类型,因为方法的参数中的函数的参数类型可以推断出函数的参数的类型
println(m5(7, 3, (a, b) => {
a + b
}))
// 1.2 {}可以省略,因为只有一行语句
println(m5(7, 3, (a, b) => a + b))
// 1.3 因为 函数的参数在函数体中只有过一次,所以可以用_代替
println(m5(7, 3, _ + _))
// 1.4 如果函数只有一个参数则() 可以省略
println(m6(9, (a: Int) => a))
println(m6(8, a => a))
//
// ==============================不能使用_的情况=======================
println("#"*3)
// 1.1如果函数参数只有一个,并且在函数体中直接返回参数本身,则参数不能用_代替
//println(m6(6, _)) 运行报错
// 1.2 如果函数体中有(),而且函数的参数处于函数体的()中,则不能用_代替
// m3((_+1)*10) 编译报错
}
// 把函数当做参数传入到方法中,函数名:(参数类型)=>返回值类型 可以把[(参数类型)=>返回值类型] 当做参数类型
// 类比 参数名:参数类型
def m1(a:Int,b:Int,func:(Int,Int)=>Int)= {
func(a,b)
}
def m2(func:(Int,Int)=>Int)=func(10,20)
def m3(func:Int=>Int)=func(50)
// 把参数当做返回值
def m4()={
var func=(x:Int,y:Int)=>x+y
// 函数就是一个对象,可以直接返回
func
}
def m5(a:Int,b:Int,func:(Int,Int)=>Int)=func(a,b)
def m6(a:Int,func:Int=>Int)=func(a)
}
7、柯里化
1、定义: 有多个参数的列表的方法称之为柯里化
2、语法: def 方法名(参数名:参数类型,..)(参数名:参数类型,..).. = {方法体}
3、柯里化出现的原因:因为函数是对象,方法可以将函数作为返回值
def m1(x:Int) = {
val func = (y:Int) =>{
val func1 = (z:Int) => x+y+z
func1
}
func
}
m1(10)(20)(30)
package com.zhijm.Day02
/**
* 柯里化:有多个参数列表的方法称为柯里化
* 作用:1简化嵌套函数开发
* 2,将复杂的参数逻辑简单化,可以支持更多的语法
*/
object $09_CurryFunction {
def main(args: Array[String]): Unit = {
//println(fun(1, 2)(2)(6))
// 方法里返回方法,层层调用
var fun2=fun1(1,2)
var fun3=fun2(3)
println(fun3(4, 5))
println("简化写法")
var result=fun1(1,2)(3)(4,5)
println(result)
}
def fun(a:Int,b:Int)(c:Int)(d:Int) = a+b+c+d
def fun1(a:Int,b:Int)={
def fun2(c:Int)={
def fun3(d:Int,f:Int):Int={a+b+c+d+f}
fun3 _
}
fun2 _
}
def func(a:Int)(b:Int)(func:(Int,Int)=>Int)=func(a,b)
}
8、闭包
1、定义: 函数体中使用不属于函数本身变量的一个函数
val y = 10
val func = (x:Int) =>x+y
//func函数体中使用y变量,y变量不属于函数本身
package com.zhijm.Day02
import java.util
import scala.collection.mutable
/**
* 闭包:闭包函数,在函数体中使用了不属于函数本身的变量
* 闭包:函数在使用外部变量,如果外部变量失效时,会将这个变量包含到当前的函数内部
* 形成闭合的使用效果,改变变量的生命周期 将这种操作称之为闭包
*
* 匿名函数肯定为闭包
* 将函数赋值给变量使用也是闭包
* 嵌套的内部函数在外面使用(使用内部函数)也是闭包
* private static final int func1$1(int b, int a$1)
* {
* return a$1 + b;
* }
* 2.12版的scala闭包的实现是利用传参的方式把被弹栈的变量传给下一个方法
*/
object $10_Closure {
def main(args: Array[String]): Unit = {
// println(func(3)(4))
// println(func3(3)(4))
var data=new util.HashMap[String,String]()
data.put("scala","baidu.com")
data.put("good","wangyi.com")
data.put("hello","guigu.com")
var array=Array("scala","good","hello")
def map(array: Array[String],func:String=>String) ={
for (word<-array) yield
func(word)
}
println(map(array, data.get(_)).toBuffer)
}
def func(a: Int) = {
def func1(b: Int) = a + b
func1 _
}
var func3 = (a: Int) => {
var func4 = (b: Int) => a + b
func4
}
}
9、递归
1、定义: 在方法体中自己调用自己
2、递归方法必须满足两个条件
1、必须要有方法的退出条件
2、递归方法必须定义返回值类型
package com.zhijm.Day02
/**
* 普通递归
* 递归:自己调用自己
* 1:在方法体中要有退出条件
* 2:方法必须定义返回值类型
*
* 尾递归
* 递归的方法不依赖于其他外部的变量
* 编译器碰见尾递归操作的时候自动化优化为while循环
*/
object $11_Recursive {
def main(args: Array[String]): Unit = {
//println(func(5))
//println(func2(5,1))
var function0=(num:Int,num2:Int)=>{num+num2}
println(function0(2, 4))
}
/**
* 普通递归
* @param number
* @return
*/
def func(number: Int):Int={
if (number == 1) {
1
}else {
number +func(number - 1)
}
}
/**
* 尾递归
* 尾递归其实就是从尾部开始进行数据的处理
* 比如
* 4 5+1
* 3 4+5+1
* 2 3+4+5+1
* 1 2+3+4+5+1
*/
def func2(num:Int,result:Int):Int={
if (num==1){
result
}else{
func2(num-1,result+num)
}
}
def fun3(num:Int,startNun:Int):Int={
if (num==1){
startNun
}else{
fun3(num-1,num+startNun)
}
}
}
10、惰性求值
1、定义: 在真正使用的使用的是才赋予初始值,而不是在定义变量的时候就赋予初始值
2、语法: lazy val 变量 = 变量值
package com.zhijm.Day02
/**
* 懒加载
* lazy延迟加载功能是编译器在编译时产生大量的方法进行调用所实现
* 用到数据的时候加载数据
*/
object $13_Lazy {
def main(args: Array[String]): Unit = {
def func()={
val sql=
"""
|select *
|from student
|where name like "%张%"
|""".stripMargin
println("#"*20)
sql
}
// 用到f变量的时候再去执行方法
lazy val f= func()
// 此处逻辑执行时间一个小时
println("执行一个小时")
// 再使用从数据库中查询出来的数据
println(f)
}
}
5、面向对象
1、包
1、包声明
1、在文件的第一行通过package 包名
2、在scala的文件中通过package 包名{...}
2、导入包
1、导入所有类: import 包名._
2、导入包中某一个类: import 包名.类名
3、导入包中多个类: import 包名.{类名,类名,..}
4、导入包中某个类,并起别名: import 包名.{类名=>别名}
5、导入包下除开某个类的所有类: import 包名.{类名=>_,_}
package com.zhijm.Day03
//导入包下所有类: import 包名._
import scala.collection.mutable._
//导入包下单个类: import 包名.类名
import scala.collection.mutable.ArrayBuffer
//导入包下多个类: import 包名.{类名1,类名2,..}
import scala.collection.mutable.{ArrayBuffer,ArrayBuilder}
//导入包下类,并起别名:import 包名.{类名=>别名}
import scala.collection.mutable.{ArrayBuffer=>myBuffer}
//导入包下除开某个类的其他的所有类:import 包名.{类名=>_,_}
import java.util.{HashMap=>_,_}
/**
* scala 中package操作
* 1 声明包
* (1)第一行声明包
* (2)在文件中通过package 包名
* 2导入包
* (1)导入包下所有的类:package 包名._
* import scala.collection.mutable._
*
* (2)导入包下单个类:import 包名.类名
* import scala.collection.mutable.ArrayBuffer
*
* (3)导入包下多个类:import 包名.{类名1,类名2...}
* import scala.collection.mutable.{ArrayBuffer,ArrayBuilder}
*
* (4)导入包下类,并起别名:import 包名.{类名=>别名}
* import scala.collection.mutable.{ArrayBuffer=>myBuffer}
*
* (5)导入包下除开某个类的其他的所有类:import 包名.{类名=>_,_}
* import java.util.{HashMap=>_,_}
* 3 注意:
* scala可以在任何地方导包,如果不是在文件开头导包,
* 那么其他地方导入包只能在当前作用域以及子作用域中使用
* 4 包对象(相当于一个工具类)
* 包对象中定义的方法与属性可以在包中任何地方使用,作用与包下的所有的类
*/
object $06_Package {
def main(args: Array[String]): Unit = {
// 使用导包的使用使用自定义命名
def myBuffer=new myBuffer
println(myBuffer.size)
// 在main方法中引入自定义的包
import myPackage._
// 使用person中的方法
person.show
}
}
package myPackage{
class person
object person{
def show=println("自定义包")
def main(args: Array[String]): Unit = {
// 包对象中的方法
packageObject()
println("hello package")
}
}
}
3、包对象
1、定义语法: object package 包名{..}
2、包对象中定义的属性以及方法和函数可以在包中任何地方进行使用
2、类和对象
1、创建类: class 类名{..}
2、创建对象: new 类名(..)
3、类的属性: class 类名{
[修饰符] val/var 变量名:变量类型 = 值
}
类中var定义的数可以通过_赋予初始值,在通过_赋予初始值的时候,属性的类型必须定义
val定义的属性不可以被重写赋值
var定义的属性可以被重新赋值
package com.zhijm
package object Day03 {
def packageObject()={
println("包对象,作用于整个包下的所有的类")
}
}
package com.zhijm.Day03
object $01_CreateClass {
class person
/**
* scala中没有public关键词,默认就是相当于public
* class 类型名{}
* scala中如果class中不需要定义与方法,{} 可以省略: class 类名
* scala中创建对象的时候,如果不需要传参数,()可以省略
* @param args
*/
def main(args: Array[String]): Unit = {
val person =new person
println(person)
/*class person{
val name= "张三"
val age=20
}
var person=new person
println(person.name)
*/
}
}
4、方法
class 类名{
[修饰符] val/var 变量名:变量类型 = 值
[修饰符] def 方法名(参数名:参数类型,..):返回值类型 = {方法体}
}
package com.zhijm.Day03
object $02_ClassFieldMethod {
class Person{
/*
定义属性
修饰符 val/var 变量名:变量类型=值
成员属性:
成员变量用val定义后,不能再被重新赋值
成员变量如果使用var定义,有默认的set方法[属性名=值],也就是可以直接赋值
成员属性的默认值规定:
成员变量用var修饰的时候,可以使用 _ 赋默认值,引用类型默认值 null int:0 double:0.0 Boolean:flase
*/
val name="lisi"
var age:Short=_
def add(x:Int,y:Int)=x+y
}
def main(args: Array[String]): Unit = {
val person=new Person
println(person)
// 1使用类中的成员
println(person.age)
println(person.name)
println(person.add(1,2))
//2修改成员变量的值
//2.1 var修饰的成员变量是可以修改的
person.age=29
// 2.2val修饰的成员属性是不能修改的
//person.name="张三" 报错
}
}
5、构造器
scala中构造器分为两种:
1、主构造器:定义在类名后面的称为主构造器
class 类名([修饰符] [val/var] 属性名:属性类型 = 默认值,..)
val/var定义的属性与不使用val/var定义的属性的区别:
val/var定义的属性可以在类外面进行调用
不用val/var定义的属性只能在class内部使用
2、辅助构造器: 定义在class里面
语法:
def this(参数名:参数类型,...) = {
辅助构造器第一行必须调用其他的辅助构造器或者主构造器
}
package com.zhijm.Day03
object $03_ConstructMethod {
/**
* scalade 构造器分为两种:主构造器,辅助构造器
* 主构造器:定义在类名后面通过([private val/var] 变量名:变量类型 [=默认值])表示
* val:定义的参数不能被重新赋值
* var:定义的参数可以被重新赋值
* val/var:定义的参数直接可以当做class的成员属性来进行使用,可以在外部通过对像
* 获取或者赋值
* 没有val/var:定义的参数只能在class的内部使用
* 辅助构造器:
* 定义位置:辅助构造器定义在class内部
* 语法:def this(变量名:变量类型,...){
* 主构造器/其他辅助构造器 // 辅助构造器第一行必须调用主构造器其他的辅助构造器
*
* }
* @param name
* @param age
* @param address
*/
class Person(val name:String="李四",var age:Int,address:String,val className:String){
/* def getAddress()={
address
}*/
private var withdraw=90
}
class Student(val name:String="李四",var age:Int,var address:String){// 主构造器
// 辅助构造器的参数声明=>变量名:变量类型 不能使用val/var 因为主构造器中已经声明过了
// 辅助构造器要经过初始化主构造器才能初始化
def this(name:String)={ // 辅助构造器
// 使用变量名进行赋值
this(name=name,age=23,address="深圳")// 显示调用主构造器,->可以使用默认的值
}
// 辅助构造器可以重载
def this(age:Int)={
this(age=age,address="上海")
}
}
def main(args: Array[String]): Unit = {
val person=new Person("张三",23,"深圳","0523")
// 1 使用val/var修饰的参数直接变成class的成员变量,有点像全局变量,
println(person.name)
println(person.age)
println(person.className)
//var修饰的可以修改值 val修饰的不能改变值
person.age=90
//person.name="333"
// 2 不使用val/var修改的参数,只能在class的内部使用,class的外部不能使用,有点像局部变量
//println(person.getAddress())
var student =new Student(23)
println("#"*20)
println(student.age)
println(student.address)
println(student.name)
}
}
6、封装
scala中为了兼容java,提供了一个注解@BeanProperty,通过该注解会自动的生成java的get/set方法
@BeanProperty注解不能标注在private修饰的属性上 ******
package com.zhijm.Day03
import scala.beans.BeanProperty
object $05_Extends {
class Person{
@BeanProperty
val name="张三"
//@BeanProperty
var age:Int=20
//@BeanProperty
val addres="shanghaoi"
def m1(i:Int,j:Int)= i+j
}
class Student extends Person {
// val 修饰的非private修饰的属性重写
override val name="李白"
override val addres="深圳"
// var修饰的属性 加上override后编译不报错,但是运行报错
//override var age=30
// 方法重写
override def m1(i: Int, j: Int): Int = i*j
}
/**
* 1 继承
* 那些不能被继承:
* 1,final修饰的class不能被继承
* 2,private修饰的属性不能被继承
*
* 父类var标识的属性不能被重写
* 子类想要重写父类的方法必须通过override关键字标识
* 子类可以重写父类val标识的非private的属性
*
*2 多态
* scala的多态不仅仅是方法的多态,属性也是多态的
*/
def main(args: Array[String]): Unit = {
// 继承
val student=new Student
println(student.getName)
// 取的是父类的age值
println(student.age)
println(student.addres)
println("多态"*3)
val person:Person=new Student
println(person.addres)
println(person.age)
println(person.name)
// 子类没有重写name和address的get和set的方法,但是调用name和address的
// get和set的方法的使用值是子类的,属性也是多态的
println("属性多态"*4)
var s=new Student
println(s.getName)
println(s.addres)
var person1:Person=s
println(person1.getName)
println(person1.addres)
}
}
7、继承
1、通过extends关键字实现继承关系
class Person
class Student extends Person
2、哪些不能被继承
1、final修饰的class不能够被继承
2、父类的private修饰的属性与方法不可被继承
3、重写
1、方法的重写
1、子类重写父类的方法必须通过 override关键字标识
2、属性的重写
1、val修饰的属性才能够通过override标识重写
2、var修饰的属性不能够重写
4、子类调用父类的方法:
子类调用父类的方法通过 super.方法名(..)
8、抽象类
1、定义语法: abstarct class 类名{..}
2、抽象类中既可以定义抽象方法[没有方法体的称之为抽象方法]也可以定义具体方法
抽象类中既可以定义抽象字段[没有赋予初始值的属性称之为抽象字段]也可以定义具体字段
package com.zhijm.Day03
/**
* 抽象类:
* 1,抽象中既可以定义具体的方法也可以定义抽象方法
* 2,抽象类中如果定义了抽象方法,子类如果不是抽象类,那么就必须重写父类的抽象方法
* 3,抽象类中既可以定义抽象属性[没有初始值的属性] 也可以定义具体属性
*/
object $07_AbstractClass {
abstract class Person{
val name="张三"
// 抽象属性
var age:Int
def add(x:Int,y:Int)=x+y
// 抽象方法
def sun(i:Int,j:Int):Int
}
// 继承抽象类
class student extends Person{
// 重写抽象属性
override var age: Int = 25
// 重写抽象方法
override def sun(i: Int, j: Int): Int = i*j
}
def main(args: Array[String]): Unit = {
// 多态
val person:Person=new student
// 调用子类重写的age属性
println(person.age)
// 调用父类本身的属性
println(person.name)
// 调用子类的重写的sun方法
println(person.sun(1, 45))
// 匿名类的定义和使用
val teacher=new Person {
override var age: Int = 23
override def sun(i: Int, j: Int): Int = i+j
}
println("teacher"*10)
println(teacher.name)
println(teacher.age)
println(teacher.sun(3,5))
}
}
9、匿名子类:
new 抽象类{ 重写抽象方法/字段 }
10、单例对象
1、定义语法: object 类名{...}
2、scala中没有static关键字,object中的属性与方法就相当于java static修饰的,所以可以通过object名称.属性/方法 进行调用
11、伴生类与伴生对象
必须满足两个条件才能称之为伴生类与伴生对象:
1、class与object的名称必须一样
2、class与object必须在同一个.scala文件中
特性: 伴生类与伴生对象可以互相访问对方的private修饰的属性/方法
apply方法: 用来简化伴生类的对象的创建 *****
apply必须定义在伴生对象中。
伴生对象中定义好apply方法之后,后续创建伴生类的对象可以通过:
1、object名称.apply(..)
2、object名称()
package com.zhijm.Day03
/**
* 单例对象:只有一个实例
* scala中单例对象就是object.如果想要创建一个单例对象,只需要创建一个object就可以
* object中所有方法和属性都是类似java.static修饰的,可以直接通过object名称.方法名/属性名
*
* 伴生对象和伴生类
* 1,class,object必须名字一样
* 2,class,object必须在同一个源文件[.scala]中
* 伴生类和伴生对象可以互相访问对方private修饰的属性与方法
*
* apply方法
* 注意:只能定义在伴生对象中,apply方法是用来简化伴生类的对象创建
* 作用:如果伴生类声明为private的时候,无法通过new的方法进行对象的创建
* 可以使用apply方法进行对象的创建
* 类对象的创建方式:
* 1,new
* 2 apply
*/
object $08_SingleObject {
def main(args: Array[String]): Unit = {
// object 对象是一个单例对象
//println($08_SingleObject eq $08_SingleObject) //true
// 伴生对象和伴生类内部相互调用
//var person1:Person=new Person("李白",33)
//person.show(1,1)
// 通过apply方法进行简化类对象的创建
val person1=Person("liability",23)
// 直接调用apply方法创建对象
var person=Person.apply("张三",35)
person.show(3,4)
}
}
object Person {
private def add(x: Int, y: Int) = {
// 在伴生对象中可以访问伴生类的私有属性与方法
var person = new Person("张三", 25)
println("伴生类私有方法:" + person.add2(x, y))
println("伴生类私有属性:" + person.sex)
}
private def sum(x: Int, y: Int) = x + y
private val address = "深圳"
private var age: Int = 26
var hight:Int=167
// 使用apply定义类对象
def apply(name: String, age: Int): Person = new Person(name, age)
}
class Person private(val name:String,var age:Int){
private def add2(x:Int,y:Int)=x+y
private val sex="男"
def show(i:Int,y:Int)={
//在伴生类中可以调用伴生对象的私有的属性和方法
println("伴生对象私有属性:"+Person.address)
println("伴生对象私有属性:"+Person.age)
println("伴生对象私有方法:"+Person.sum(3, 5))
println("伴生对象私有方法:"+Person.add(i, y))
}
}
12、特质
1、定义: trait 特质名{..}
2、scala是单继承,多实现
3、特质中既可以定义抽象方法[没有方法体的称之为抽象方法]也可以定义具体方法
特质中既可以定义抽象字段[没有赋予初始值的属性称之为抽象字段]也可以定义具体字段
4、特质的继承
1、子类如果需要继承class,此时想要继承trait,必须通过with关键字来实现
trait Log
class Person
class Student extends Person with Log
2、子类不需要继承class,此时继承第一个trait的时候通过extends关键字实现,后续其他的trait通过with关键字实现
trait Log
trait Log2
class Dog extends Log with Log2
5、特质的方法的执行顺序
1、子类可以实现多个特质,如果这多个特质中都有一个同名的方法,子类需要重新父类的同名方法
2、如果这多个特质都继承自同一个父特质,子类重写同名方法之后,调用方法,方法的执行顺序是按照继承的顺序从右向左开始执行,最后才会执行共同的父特质
6、特质的实例化的顺序:
根据继承的顺序从左向右开始实例
7、特质自身类型: 子类要想实现特质必须先实现/继承指定的特质/class
1、语法:
trait 特质名{
this:特质名/class名 =>
}
8、类型检查、转换
1、判断类型: 对象.isInstanceOf[类名]
2、类型转换: 对象.asInstanceOf[类名]
9、获取class形式 ******
1、获取类的class形式: classOf[类名]
2、获取对象的class形式: 对象.getClass
10、枚举、App
1、App: 子类继承App之后,不需要定义main方法,类中的所有的都是相当于写在main方法中
2、枚举
11、定义新类型: type 类型名称 = 类名
package com.zhijm.Day03
/**
* 对象混入trait:只让某些对象拥有trait对应的属性和方法
* 如果有些对象需要用到特质中的有些功能,但是又不想全部对象都有这些功能
* 这时候可以用混入特质
*/
object $10_TraitObject {
class tigger {
val name = "老虎"
}
trait log {
def add(i: Int, j: Int) = i + j
}
class Cat {
val name: String = "小黄"
val age: Int = 23
def show(): Unit = println(s"名称:${name},年龄:${age}")
}
def main(args: Array[String]): Unit = {
val cat=new Cat with log
println(cat.add(1, 55))
// var tigger = new tigger with log
// println(tigger.add(1, 2))
}
}
package com.zhijm.Day03
/**
* 1 继承多个有相同方法的trait时会出现报错的问题
* (1)scala 中可以实现多个trait,如果这么多个trait(没有共同的父类)都有相同的同名方法,
* 此时子类创建的对象在执行的时候就会报错
* (2)解决方法:直接重写同名方法,如果在方法中调用父类的同名方法,实际上调
* 用的是实现顺序中最后一个trait的同名方法
* (3)同名方法的执行顺序[继承的多个trait有一个共同的父trait/class]:
* ①如果同名方法中都调用了父类的同名方法:按照继承顺序从右往左执行
* ②如果只有子类调用了父类的同名方法:按照继承顺序从左往右执行
* (4)继承trait时实例化的顺序:按照继承/实现的顺序从左往右开始示例化(父类时第一个开始实例化的)
*
**
*/
trait Log{
println("Log=======================")
def log(msg:String)=println(s"log $msg")
}
trait ErrorLog extends Log{
println("ErrorLog========================")
override def log(msg:String)={
println(s"error++ $msg")
super.log(msg)
}
}
trait WarnLog extends Log{
println("WarnLog========================")
override def log(msg:String)={
println(s"warn $msg")
super.log(msg)}
}
trait ErrorLog1 {
println("ErrorLog========================")
def log(msg:String)=println(s"error $msg")
}
trait WarnLog1{
println("WarnLog========================")
def log(msg:String)=println(s"warn $msg")
}
class AppLog extends WarnLog1 with ErrorLog1{
println("AppLog=======================")
// 子类重写两个父类的相同方法后,子类对象调用时会调用自己的方法
// 如果在方法中调用父类的方法,则从左往右进行方法的覆盖
override def log(msg: String): Unit = super.log(msg)
}
class AppLog1 extends WarnLog with ErrorLog{
println("AppLog=======================")
override def log(msg: String): Unit ={
println(s"appLog1=====================$msg")
super.log(msg)
}
}
object $11_TraitMethod {
def main(args: Array[String]): Unit = {
//val appLog=new AppLog
// (1)scala 中可以实现多个trait,如果这么多个trait(没有共同的父类)都有相同的同名方法,
// 此时子类创建的对象在执行的时候就会报错
// appLog.log("good") //没有重写相同方法时,运行报错
// (4)继承trait时实例化的顺序:按照继承/实现的顺序从左往右开始示例化(父类时第一个开始实例化的)
val appLog1=new AppLog1
appLog1.log("hello")//error++ hello warn hello
}
}
package com.zhijm.Day03
/**
* App:代替main的方法,具有main方法的功能
* 一般不用
* type:给数据类型取别名
* Enumeration:枚举类
*/
object $12_App extends App {
println("good")
}
object TypeTest{
type s=String
def main(args: Array[String]): Unit = {
val name:s="ggg"
println(name)
println(Color.BLUE)
}
}
object Color extends Enumeration{
val RED=Value(1,"red")
val YEELLOW=Value(2,"red")
val BLUE=Value(3,"red")
}
package com.zhijm.Day03
import java.io.{FileInputStream, FileOutputStream, ObjectInputStream, ObjectOutputStream}
import scala.beans.BeanProperty
/**
* obj.isInstanceOf 类型判断
* obj.asInstanceOf 类型转换
* _:类=>:自身类型提醒
*/
object $12_SelfType {
// 自身类型:提醒子类要实现该trait的时候必须提前实现指定的trait/class
trait ReadAndWriteObject{
_:Serializable=>
def read()={
val ois=new ObjectInputStream(new FileInputStream("D:/object.txt"))
var obj=ois.readObject()
ois.close()
// 返回
obj
}
def write()={
val ous=new ObjectOutputStream(new FileOutputStream("D:/object.txt"))
ous.writeObject(this)
ous.flush()
ous.close()
}
}
class Person(@BeanProperty val name:String,@BeanProperty val age:Int) extends ReadAndWriteObject with Serializable
def main(args: Array[String]): Unit = {
val person=new Person("李白",26)
person.write()
var person2=new Person("张三",56)
var obj=person2.read()
// 类型判断
if(obj.isInstanceOf[Person]){
//类型转换
val person3 = obj.asInstanceOf[Person]
println(person3.getAge)
println(person3.getName)
}
/*obj match {
case person1: Person =>
// 类型转换
person2 = person1
case _ =>
}*/
println(person2.name)
println(person2.age)
}
}
package com.zhijm.Day03
import com.alibaba.fastjson.JSON
/**
* 获取类的class: classOf[类名]
* 获取对象的class: 对象.getClass
*/
import scala.beans.BeanProperty
object $13_ClassOf {
class Person(@BeanProperty val name:String,@BeanProperty val age:Int)
case class Student(name:String,age:Int)
def main(args: Array[String]): Unit = {
val json=
"""
|{"name":"lisi","age":12}
|""".stripMargin
//java:
// 1、根据类获取class。类名.class
// 2、如果根据对象获取class。 对象.getClass
var person=JSON.parseObject(json,classOf[Person])
println(person.age)
println(person.name)
var student=JSON.parseObject(json,classOf[Student])
println(student.age)
println(student.name)
}
}
6、集合
1、scala中集合分为两种:
可变集合[集合长度可变]、不可变[集合长度不可变]集合
2、数组
1、可变数组
1、创建方式:
1、new mutable.ArrayBuffer[元素的类型](数组的长度)
2、ArrayBuffer[元素的类型](初始元素,..)
2、操作
1、查看某个角标的元素: 数组变量名(角标)
2、修改某个角标的值: 数组变量名(角标) = 值
3、添加数据
4、删除数据
package com.zhijm.Day04
/**
* 1、创建不可变数组:不能新增和删除,可以修改
* 1、 new Array[元素类型](长度)
* 2、 Array[元素类型](初始元素,..)
* 2、增删改查
* 1、获取元素: 数组(角标)
* 2、修改元素的值: 数组(角标) = 值
* 3、添加元素[实际上是生成一个新的数组,原有的数组没有变化]
* 添加单个元素: +:与:+的区别【+:将元素添加到最前面,:+将元素添加到最后面】
* val 新数组 = 数组.+:(元素)
* val 新数组 = 数组.:+(元素)
* 添加集合的所有元素: ++ 、++: [++将一个数组的所有元素添加到最后面,++:将一个数组的所有元素添加到最前面]
* val 新数组 = 数组.++(数组2)
* val 新数组 = 数组.++:(数组2)
*
* 不可变数组转可变数组: toBuffer
*/
object $01_ImmutableArray {
def main(args: Array[String]): Unit = {
// 1 new Array[类型](长度) 没有赋初始值,默认是0
var array=new Array[Int](3)
var array1=array.+:(1)
println(array1.toBuffer)
// 2 Array[类型](初始元素) 调用的是apply[T: ClassTag](xs: T*)方法
var arr=Array[Int](34,5,6,7)
println(arr.toBuffer)
// 3 获取数据:数组对象(角标)
println(arr(0))// 获取第一个元素
// 4 修改数据
arr(0)=1000
println(arr.toBuffer)
// 5 添加单个元素 添加元素的时候只会生成一个新的数组,原来的数据没有改变
var arr1=arr.+:(90) // 把元素添加在原来元素的前面
var arr2=arr.:+(80)// 吧元素添加在原来元素的后面
println(arr1.toBuffer)
println(arr2.toBuffer)
// scala中==与eqauls含义一样,如果想判断两个对象是否是同一个,需要通过eq方法来判断
println(arr1.eq(arr))
// 6 添加集合的所有的元素
var appendArr=Array[Int](3,4,5,6,7)
var arr3=arr.++(appendArr) // 添加到数组的后面
println(arr3.toBuffer)
var arr4=arr.++:(appendArr)
println(arr4.toBuffer) // 添加集合的所有的元素到数组的前面
}
}
2、不可变数组
1、创建方式:
1、new Array[元素的类型](数组的长度)
2、Array[元素的类型](初始元素,..)
2、操作
1、查看某个角标的元素: 数组变量名(角标)
2、修改某个角标的值: 数组变量名(角标) = 值
3、添加数据[不可变数组添加数组会生成新的数组,原有的数组不会改变]
package com.zhijm.Day04
import scala.collection.mutable.ArrayBuffer
/**
* 创建可变数组: ArrayBuffer[元素类型](初始元素,...)
* 单个+/-与两个+/-的区别: 单个+/-针对的是单个元素,两个+/-针对是一个集合的所有元素
* +与-的区别: +代表添加元素,-代表删除元素
* 带=与不带=的区别: 带=修改的是集合本身,不带=创建一个新集合,原有集合不变
* :在前与:在后的区别: :在前面代表添加元素到最后面,:在后代表添加元素到最前面。不带:是将元素添加到最后面
* 添加数据
* 删除
* 查看
* 修改数据
* 可变数组转不可变数组: toArray
*/
object $02_MutableArray {
def main(args: Array[String]): Unit = {
// 1 创建可变数组
var array=ArrayBuffer[Int](1,5,6,7,8,4)
println(array)
// 2 修改指定角标的值
array(0)=100
println(array)
//3 获取指定角标的值
println(array(2))
// 4,添加元素->生成新集合
//4.1 添加单个元素->生成新集合
var arr2=array.+:(40)// 添加在原来元素的前面
var arr3=array.:+(50) // 添加在原来元素的后面
println(arr2)
println(arr3)
// 4.2 添加集合里的元素->生成新集合
var arr4=array.++(arr3)// 添加在原来元素的前面
var arr5=array.++:(Array(1,4,5,6,7)) // 添加在原来元素的后面
println(arr4)
println(arr5)
//5添加元素->改变集合的本身
//5.1 添加单个元素
println("改变集合的本身")
println(array)
array.+=(56) // 添加在集合的后面
println(array)
array.+=:(78)
println(array)
//5.2 添加整个集合元素
println("添加集合中的元素")
array.++=(Array(1,2,5,6))
println(array)
array.++=:(Array(66,88,99))
println(array)
// 6 删除元素 不改变自身
//6.1 删除一个元素 根据元素 不是根据索引删除的,而是根据元素匹配删除
val buffer = array.-(88)
println(buffer)
val array6 = array.-(0)
println(array6)
// 6.2 删除整个集合里的元素 删除匹配数组里的元素
val array7 = array.--(Array(88, 99, 66,55))
println(array7)
// 7 删除元素 改变本身
// 7.1 删除单个元素
val array8 = array.-=(99)
println(array8)
// 7.2 删除匹配的数组的元素
val array9 = array.--=(Array(88, 66))
println(array9)
// 8 创建多维数组
val array10 = Array.ofDim[Int](3, 3)
println(array10)
for (arr<-array10){
for (i<-arr)
println(i)
}
}
}
2、List
1、可变
1、创建方式: mutable.ListBuffer[元素类型](初始元素,..)
2、查看某个角标的元素:list变量名(角标)
3、修改某个角标的值: list变量名(角标) = 值
4、添加数据
5、删除
package com.zhijm.Day04
import scala.collection.mutable.ListBuffer
/**
* 创建可变的list集合:ListBuffer[类型](值....)
*/
object $04_MutableList {
def main(args: Array[String]): Unit = {
// 1创建可变的list集合
val listBuffer = ListBuffer(1, 2, 3, 4, 50)
// 2,获取数据 list(角标)
println(listBuffer.head)
println(listBuffer(3))
// 3 修改数据
// 3.1 修改集合的本身
listBuffer.update(0, 100)
println(listBuffer)
// 3.2 生成新的集合,不修改本身
val listBuffer1 = listBuffer.updated(1, 555)
println(listBuffer1)
// 4,添加元素
//4.1 生成新的集合 添加单个元素
val listBuffer2 = listBuffer.+:(99)
println(listBuffer2)
val listBuffer3 = listBuffer.:+(889)
println(listBuffer3)
// 4.2 修改集合本身, 添加单个元素
listBuffer.+=(909)
println(listBuffer)
val listBuffer4 = listBuffer.+=:(8899)
println(listBuffer4)
//4.3 生成新集合 添加整个集合数据
val listBuffer5 = listBuffer.++(List(90, 33, 444))
println(listBuffer5)
val listBuffer6 = listBuffer.++:(List(3, 5, 6))
println(listBuffer6)
// 4.4 改变集合本身,添加整个集合的数据
listBuffer.++=(List(909,888))
println(listBuffer)
val listBuffer7 = listBuffer.++=:(List(55, 8888))
println(listBuffer7)
// 5 删除数据
// 5.1 生成新集合 删除一个元素
val listBuffer8 = listBuffer.-(8888)
println(listBuffer8)
// 5.2 删除本身 删除一个元素
listBuffer.-=(888)
println(listBuffer)
//5.3 删除一个集合 生成一个新的集合
val listBuffer9 = listBuffer.--(List(55, 8888))
println(listBuffer9)
// 5.4 删除一个集合 修改本身
listBuffer.--=(List(55,8888))
println(listBuffer)
}
}
2、不可变
1、创建方式: List[元素类型](初始元素,..)
2、查看某个角标的元素:list变量名(角标)
3、修改某个角标的值: list变量名(角标) = 值
4、添加数据
:: 添加单个元素,元素添加在头部
::: 添加一个集合的所有元素,元素添加在头部
package com.zhijm.Day04
/**
* 创建不可变list:List[数据类型](值)
*/
object $03_ImmutableList {
def main(args: Array[String]): Unit = {
// 1创建
val list = List[Int](1, 2, 3, 4)
// 2获取元素 list(角标)
val number = list.head
println(number)
val number2 = list(3)
println(number2)
// 3 修改集合 生成新的集合,原来的集合不改变
val list2 = list.updated(0, 199)
println(list2)
//4 添加元素 生成新的集合,原来的集合不改变
// 4.1 添加单个元素
val list1 = list.+:(78)
println(list1)
val list3 = list.:+(999)
println(list3)
val list4= list.::(888)// 加在集合的最前面
println(list4)
//4.2 添加一个集合的所有的元素
val list5 = list.++(List(90, 34, 56))
println(list5)
val list6 = list.++:(List(889, 23))
println(list6)
// 加在集合的最前面
val list7 = list.:::(List(89, 90, 88))
println(list7)
}
}
3、Set
Set中的数据无序,不重复
1、可变
1、创建方式: mutable.Set[元素类型](初始元素)
2、添加数据
3、删除数据
package com.zhijm.Day04
import scala.collection.mutable.ListBuffer
/**
* 创建可变的list集合:ListBuffer[类型](值....)
*/
object $04_MutableList {
def main(args: Array[String]): Unit = {
// 1创建可变的list集合
val listBuffer = ListBuffer(1, 2, 3, 4, 50)
// 2,获取数据 list(角标)
println(listBuffer.head)
println(listBuffer(3))
// 3 修改数据
// 3.1 修改集合的本身
listBuffer.update(0, 100)
println(listBuffer)
// 3.2 生成新的集合,不修改本身
val listBuffer1 = listBuffer.updated(1, 555)
println(listBuffer1)
// 4,添加元素
//4.1 生成新的集合 添加单个元素
val listBuffer2 = listBuffer.+:(99)
println(listBuffer2)
val listBuffer3 = listBuffer.:+(889)
println(listBuffer3)
// 4.2 修改集合本身, 添加单个元素
listBuffer.+=(909)
println(listBuffer)
val listBuffer4 = listBuffer.+=:(8899)
println(listBuffer4)
//4.3 生成新集合 添加整个集合数据
val listBuffer5 = listBuffer.++(List(90, 33, 444))
println(listBuffer5)
val listBuffer6 = listBuffer.++:(List(3, 5, 6))
println(listBuffer6)
// 4.4 改变集合本身,添加整个集合的数据
listBuffer.++=(List(909,888))
println(listBuffer)
val listBuffer7 = listBuffer.++=:(List(55, 8888))
println(listBuffer7)
// 5 删除数据
// 5.1 生成新集合 删除一个元素
val listBuffer8 = listBuffer.-(8888)
println(listBuffer8)
// 5.2 删除本身 删除一个元素
listBuffer.-=(888)
println(listBuffer)
//5.3 删除一个集合 生成一个新的集合
val listBuffer9 = listBuffer.--(List(55, 8888))
println(listBuffer9)
// 5.4 删除一个集合 修改本身
listBuffer.--=(List(55,8888))
println(listBuffer)
}
}
2、不可变
1、创建方式: Set[元素类型](初始元素)
2、添加数据
3、删除数据
package com.zhijm.Day04
/**
* set 不可变的特性:无序 不重复
*/
object $05_ImmutableSet {
def main(args: Array[String]): Unit = {
// 创建set对象
val set = Set[Int](1, 3, 7, 6, 5)
// 1set没有取元素的方法
//println(set(0)) 表示set集合是否包含
// 2添加 单个元素
val set1 = set.+(66)
println(set1)
// 添加集合里的数据
val set2 = set.++(Array(2, 5, 7, 8))
println(set2)
val set3 = set.++:(Array(2, 5, 7, 0))
println(set3)
// 删除元素
val set4 = set.-(1)
println(set4)
// 删除集合的数据
val set5 = set.--(set)
println(set5)
}
}
4、Map
1、可变
1、创建方式:
1、mutable.Map[K的类型,V的类型]( (K,V),(K,V),.. )
2、mutable.Map[K的类型,V的类型]( K->V,K->V,...)
2、获取key对应的value值: map变量.getOrElse(K,默认值)
默认值是当查询map中不存在的key的时候返回的值
3、修改value: map变量(K) = value
4、添加
map变量.put(K,V)
5、删除
map变量.remove(K)
package com.zhijm.Day04
import scala.collection.mutable
/**
*
* 可变的,map集合
* 创建map:
* 1、Map[K的类型,V的类型]( K -> V,K->V,..)
* 2、Map[K的类型,V的类型]( (K,V),(K,V))
*/
object $08_MutableMap {
def main(args: Array[String]): Unit = {
val map = mutable.Map[String, Int]("lisi" -> 23, "zhangsan" -> 25, "wangwu" -> 26)
println(map)
// 获取key对应的value
val age = map.getOrElse("zhangsan", 2)
println(age)
// 修改value值[如果key存在,则修改,如果不存在则插入]
map("zhangsan")=88
map("zhaoyun")=99
println(map)
// 添加
val map1 = map.+("zhaoliu" -> 34)
println(map1)
map.+=("luban"->11)
println(map)
// 添加一个map集合
val map2 = map.++(mutable.Map[String, Int]("张飞" -> 24, "旋蒸" -> 56))
println(map2)
map.++=(mutable.Map[String,Int]("dubu"->44,"gej"->22))
println(map)
// 删除单个元素
println(map)
val map3 = map.-("gej")
println(map3)
map.-=("gej")
println(map)
// 删除多个元素
val map4 = map.--(List[String]("zhaoliu", "zhaoyun"))
println(map4)
map.--=(List[String]("zhaoliu", "zhaoyun"))
println(map)
}
}
2、不可变
1、创建方式
1、Map[K的类型,V的类型]( (K,V),(K,V),.. )
2、Map[K的类型,V的类型]( K->V,K->V,...)
2、获取key对应的value值: map变量.getOrElse(K,默认值)
默认值是当查询map中不存在的key的时候返回的值
3、修改value: map变量(K) = value
4、添加数据
5、删除数据
package com.zhijm.Day04
/**
* 创建map 不可变map
* 1,Map[k的类型,v的类型](k->v,k1->v1...)
* 2,Map[K的类型,v的类型]((k,v),(k,v)...)
*/
object $07_ImmutableMap {
def main(args: Array[String]): Unit = {
// 1 Map[k的类型,v的类型](k->v,k1->v1....)
val map = Map[String, Int]("zhangsan" -> 24, "lisi" -> 23, "wangwu" -> 26)
println(map)
// 2 Map[k的类型,v的类型]((k,v),(k,v))
val map1 = Map[String, Int](("李白", 23), ("张飞", 35), ("甄姬", 28))
println(map1)
// 3获取某个Key的value值
//println(map("zhangsan")) // 没有相应的key值会报错
// 所以有另一种取值的方法map.get(key)
//Option 有两个子类
// Some:代表有值,值封装在Some中
// None:代表没有值,代表提示外部进行处理
//val value: Option[Int] = map1.get("zhangsan")
//println(value.get)
//getOrElse(K,默认值)
val option = map.get("zhang")
// 取值的时候判断一下option的值
if (option ==null){
println(option.get)
}
// 还有一种简单的取值方法 如果取不到则就把默认值赋值给他
val age = map.getOrElse("张三","0")
println(age)
// 4.添加单个元素 生成新的map
val map2 = map.+("张三" -> 23)
println(map2)
// 5.添加集合的数据 随机性
val map3 = map.++(Map[String, Int]("李四" -> 23, "王五" -> 34))
println(map3)
val map4 = map.++:(Map[String, Int]("夏侯惇" -> 45))
println(map4)
// 6 删除单个元素
println("删除")
println(map)
val map5 = map.-("zhangsan")
println(map5)
val map6 = map.--(List[String]("lisi", "wangwu"))
println(map6)
// 遍历Map 集合 k-v对就是一个个元组
for (element<-map){
println(element)
}
// 获取map的所有的key值
val keys = map.keys
for (key<-keys){
println(key)
}
// 获取map的所有的value值
val values = map.values
for (value<-values){
println(value)
}
}
}
5、元组
1、创建方式:
1、通过()的方式: (元组的元素,..) [元组最多只能有22个元素]
2、创建二元元组:【二元元组在scala中是表示KV键值对】
1、(K,V)
2、K->V
2、特性: 元组一旦创建不可修改[不能改变元组的长度,也不能修改元组的值]
3、获取元组的值: 元组变量名._角标 【元组的角标从1开始】
package com.zhijm.Day04
/**
* 元组:由()包括起来的称之为元组
* 定义:
* 1:(不同类型的值) 比如val t=("张三","男",23)
* 2:二元元组:(k->v) 也就是map中的key->value
* 元组一旦定义,不但长度不可变,元素也是不可以改变的
*
* 获取元组的值:变量._角标[角标从1开始]
*/
object $09_Tuple {
def main(args: Array[String]): Unit = {
// 元组的定义
var tuple1=("李白",23,"男")
println(tuple1._1)
val tuple = ("李四", 23)
println(tuple._2)
// kv结构就是值二元元组
var tuple2="白居易"->87
println(tuple2._2)
println(tuple1)
}
def tuple1(): Unit ={
}
}
6、集合添加元组、删除元素的方法:
1、添加元素: +=、+:、:+、+、++、++:、++=、++=:
2、删除元素: -、-=、--、--=
一个+/-与两个+/-的区别:
一个+/-是针对单个元素进行操作
两个+/-是针对集合的所有元素
:在前和:在后的区别:
:在前是添加元素到最后面
:在后是添加元素到最前面
不带:是添加元素到最后面
带=与不带=的区别:
带=是修改集合本身
不带=是生成一个新的集合,原有集合不改变
7、集合操作
1、常用操作和属性
1、获取数组的长度或者大小:
1、length
2、size
2、遍历: for(变量<-集合)
3、生成字符串:
mkString(分隔符) : 通过指定的分隔符将集合的所有元素拼接起来
4、是否包含某个元素: contains(元素)
5、判断是否为空: isEmpty
package com.zhijm.Day04
object $10_CollectionFunction {
def main(args: Array[String]): Unit = {
// 基本属性与常用的操作
val list = List[Int](2, 4, 5, 7, 8)
// 查看集合的长度
println(list.size)
println(list.length)
// 遍历集合
for (num<-list){
println(num)
}
// 生成字符串
println(list.mkString("@"))
// 是否包含
println(list.contains(3))
}
}
2、衍生集合
1、获取第一个元素: head
2、获取最后一个元素: last
3、获取前几个元素: take(n)
4、获取后面几个元素: takeRight(n)
5、获取除开前面几个元素其他所有元素: drop(n)
6、获取除开最后几个元素的其他所有元素: dropRigth(n)
7、获取除开第一个元素的所有元素: tail
8、获取除开最后一个元素的所有元素: init
9、去重: distinct
10、反转:reverse
11、划窗: sliding(窗口的长度,滑动的长度)
val list = List(1,2,3,4,5,6)
list.sliding(3,2)
=>结果:List[List[Int]]( List[Int](1,2,3), List[Int](3,4,5),List[Int](5,6))
12、拉链: zip
val list1 = List[String]("zhangsan","lisi")
val list2 = List[Int](20,30,40)
val list3 = list1.zip(list2)
=>结果: List[(String,Int)](("zhangsan",20), ("lisi",30))
13、反拉链: unzip
list3.unzip
=>结果:(List[String] ("zhangsan","lisi"),List[Int](20,30))
14、交集:intersect [两个集合共同的部分]
val list = List(1,2,3)
val list2 = List(2,3,4)
list.intersect(list2) => List(2,3)
15、差集: diff [A差B的结果就是A中有B中没有的数据]
val list = List(1,2,3)
val list2 = List(2,3,4)
list.diff(list2) => List(1)
16、并集: union [拼接两个集合,不会去重]
val list = List(1,2,3)
val list2 = List(2,3,4)
list.union(list2) => List(1,2,3,2,3,4)
17、获取子集合:
slice(from,until)
from: 代表从哪个角标开始
until: 到哪个角标结束[不包含]
val list = List(1,2,3,4,5,6)
list.slice(2,5) => List(3,4)
package com.zhijm.Day04
import scala.collection.mutable
import scala.collection.mutable.ListBuffer
object $11_CollectionFunction {
def main(args: Array[String]): Unit = {
val list = List[Int](2, 3, 5, 3, 3,1, 8, 9)
// val listBuffer = ListBuffer[Int](2, 3, 5, 3, 1, 8, 9)
// 删除前多少个元素
val list1 = list.drop(2)
println(list1)
//listBuffer.drop(2)
// println(listBuffer)
// 删除后面的多少个元素
val list2 = list.dropRight(2)
println(list2)
// 去重
val list3 = list.distinct
println(list3)
// 获取第一个元素
val head = list.head
println(head)
// 获取最后一个元素
val last = list.last
println(last)
// 获取除了最后一个元素的所有的元素
val init = list.init
println(list)
println(init)
println("除开第一个")
// 获取除了以一个元素的所有的元素
println(list)
val tail = list.tail
println(tail)
// 获取从前往后多少个元素
val list5 = list.take(3)
println(list5)
// 获取从后往前的多少个元素
val list6 = list.takeRight(3)
println(list6)
// 判断是否为空
println(list.isEmpty)
// 反转
val reverse = list.reverse
println(reverse)
// 划窗 默认的步长为1 每取两个元素形成一个list集合
val iterator = list.sliding(2)
for (i<-iterator)println(i)
// 不足步长的,就把剩余的单独形成一个list集合
val sliding = list.sliding(3, 2)
for (i<-sliding)println(i)
// 获取子集合 from:开始角标 until:结束角标[不包含]
// 左闭右开
println("="*34)
println(list)
val list4 = list.slice(1, 3)
println(list4)
// 集合的操作
//交集:取两个集合共同的部分
val list7 = list.intersect(List(8, 9))
println(list7)
// 差值 A差B 保留的是A中有 B中没有的元素
val list8 = list.diff(List(8, 9))
println(list8)
// 并集 不会去重 如果需要去重需要再调用distinct distinct
val list9 = list.union(List(2, 3, 5, 7))
println(list9)
// 拉链 A和B进行拉链操作 A的元素在前,拉链的个数取决于最短的那个集合个数
val tuples = list.zip(List("李四", "战三", "王五"))
println(tuples)
val tuples1 = List("李四", "战三", "王五").zip(list)
println(tuples1)
// 反拉链 把元组中第一个元素都取出来放入同一个list中
val unzip = tuples.unzip
println(unzip)
}
}
3、初阶函数:
1、max : 获取最大值
2、min : 获取最小值
3、sum : 求和
4、高阶函数:
1、filter(func: 集合元素类型 => Boolean): 针对集合的每个元素
filter保留的数据是函数返回值为true的数据
2、map( func: 集合元素类型 => U ): 针对集合的每个元素
场景: map用于一对一场景[集合A通过map计算得到集合B,集合B的长度=集合A的长度]
3、flatten: 压平
场景: 用于一对多场景[集合A通过flatten计算得到集合B,集合B的长度>=集合A的长度]
flatten只会压第二层
val list =List("hello","word","scala")
list.flatten => List('h','e','l','l',...)
4、flatMap( func: 集合元素类型=> 集合 ): 针对集合的每个元素
flatMap 相当于 先map然后在flatten
场景: 用于一对多场景[集合A通过flatMap计算得到集合B,集合B的长度>=集合A的长度]
5、sorted: 排序
排序的结果是升序,如果想要降序可以通过reverse反转
6、sortBy(func: 元素类型 => U ): 针对集合的每个元素
sortBy的结果也是升序
7、sortWith(lt: (元素类型,元素类型) => Boolean ): 两两比较
val list = List(10,2,3,1,5,6)
list.sortWith((x,y)=>x<y) =>升序
list.sortWith((x,y)=>x>y) =>降序
8、groupBy(func: 元素类型 => U ): 针对集合的每个元素,其实就是指定按照什么进行分组
groupBy用于多对一[集合A通过flatMap计算得到集合B,集合B的长度<=集合A的长度]
9、reduce(func: (元素类型,元素类型)=>元素类型 ) : 两两聚合,最终结果只有一个值
val list = List(10,2,3,1,5,6)
list.reduce((agg,curr)=>{..})
agg:是上一次的聚合结果[第一个聚合的时候,默认值=集合的第一个元素]
curr: 本次要聚合的元素
10、reduceRigth(func: (元素类型,元素类型)=>元素类型 ) : 两两聚合,最终结果只有一个值
val list = List(10,2,3,1,5,6)
list.reduce((curr,agg)=>{..})
agg:是上一次的聚合结果[第一个聚合的时候,默认值=集合的最后一个元素]
curr: 本次要聚合的元素
11、fold(初始值)(func: (元素类型,元素类型)=>元素类型 ): 两两聚合,与reduce唯一不同是有初始值
val list = List(10,2,3,1,5,6)
list.fold(初始值)((agg,curr)=>{..})
agg:是上一次的聚合结果[第一个聚合的时候,默认值=初始值]
curr: 本次要聚合的元素
12、foldRigth
val list = List(10,2,3,1,5,6)
list.foldRigth(初始值)((agg,curr)=>{..})
agg:是上一次的聚合结果[第一个聚合的时候,默认值=初始值]
curr: 本次要聚合的元素
package com.zhijm.Day04
import scala.collection.LinearSeq
/**
* 集合高阶函数
*/
object $13_CollectionFunction {
def main(args: Array[String]): Unit = {
//foreachTest()
//groupByTest()
//mapTest()
// flattenTest()
flatMapTest()
//sortedTest()
//sortByTest()
//sortWithTest()
//reduceTest()
//foldTest()
//foldRightTest()
}
/**
* filter :过滤 针对的是集合的每个元素,保留的是函数返回值为true的数据
*/
def filter(): Unit ={
val list: List[Int] = List[Int](2, 1, 3, 4, 6, 7, 5, 8)
val list2 = list.filter(x => x % 2 == 0)
val list1 = list.filter(_ % 2 == 0)
println(list1)
println(list2)
}
/**
* foreach循环遍历集合的每一个值
*
* @inline final override def foreach[U](f: A => U) {
* var these = this
* while (!these.isEmpty) {
* f(these.head)
* these = these.tail
* }
* }
*/
def foreachTest(): Unit ={
val list: List[Int] = List[Int](2, 1, 3, 4, 6, 7, 5, 8)
//list.foreach(x=>println(x))
//list.foreach(println(_))
// println方法符合要求
list.foreach(println)
}
/**
* groupBy 针对的是集合中的每一个元素
* 场景: 用于多对一的场景 类似sql中的group by 分组
* groupBy(f:(x)=>K)中x=>k x是list集合中的元素是函数的参数,k是函数的业务逻辑,
* 整个x=>k方法是传入x得到结果k,然后group by中的逻辑就根据k进行分组处理
* groupBy返回的是Map类型
*/
def groupByTest(): Unit ={
val list = List[(String, Int, String)](
("zhangsan", 23, "beijing"),
("lisi", 23, "shenzhen"),
("王五", 23, "shanghai"),
("赵柳", 23, "shenzhen"),
("柳岩", 23, "beijing")
)
val map = list.groupBy(x => x._3)
println(map)
}
/**
* map 针对的是集合的每一个元素
* 场景:用于一对一的场景
*map(f: A => B) 出入一个类型返回另一个类型,把list中的每一个元素传进去返回通过业务处理的另一个类型的数据
* map的返回类型也是集合list
* map flatMap filter distinct sortBy
*/
def mapTest(): Unit ={
val list = List[String]("hello", "world", "scala", "python")
val list1 = list.map(x => x.length)
println(list1)
}
/**
* 压平
* 场景 一对多
* 把集合中每一个元素传进去 返回一个或多个元素
* 注意flatten 只对第一层list中的元素进行操作
* 返回值也是集合list
*/
def flattenTest(): Unit ={
val list = List[List[Int]](
List[Int](2, 3, 4, 5),
List[Int](6, 7, 8, 9),
List[Int](10, 11, 12, 13)
)
val flatten = list.flatten
println(flatten)
}
def flattenOps(): Unit ={
val list = List[List[List[Int]]](
List[List[Int]](List[Int](1, 2)),
List[List[Int]](List[Int](3, 4)),
List[List[Int]](List[Int](5, 6))
)
val flatten = list.flatten
println(flatten)
}
/**
* 扁平化
* flatmap 针对集合的每个元素=map+flatten
* 场景:用于一对多
* flatMap是先对集合进行map操作 再对map处理后的返回值进行flatten操作
*/
def flatMapTest(): Unit ={
val list = List[String]("hello word","hello python")
//1 map + flatten
val list1 = list.map(_.split(" "))
// List[Array(hello,word),Array(hello,python)]
val flatten = list1.flatten
// list[hello,word,hello,python]
println(flatten)
//2,flatMap
val list2 = list.flatMap(_.split(" "))
println(list2)
}
/**
* sorted :按照元素本身的大小进行排序,默认是升序排序
*/
def sortedTest(): Unit ={
val list = List[Int](1, 3, 5, 3, 2, 2, 8)
val list1 = list.sorted
println(list1)
}
/**
* sortBy 针对集合的每个元素,返回的是按照排序字段进行排序的集合lsit[升序]
* sortBy(f: A => B) 传入集合的每一个元素,然后返回第二个元素,然后sortBy就按照返回的
* 值进行排序
*/
def sortByTest(): Unit ={
val list = List[(String, Int)](("zhansan", 25), ("lisi", 23), ("wangwu", 24))
val list1 = list.sortBy(_._2)
println(list1)
}
/**
* sortWith 集合的每两个元素进行比较
*
*/
def sortWithTest(): Unit ={
val list = List[Int](1, 3, 5, 3, 2, 2, 8)
//降序
val list1 = list.sortWith((x, y) => x > y)
println(list1)
// 升序
val list2 = list.sortWith(_ < _)
println(list2)
}
/**
* reduce
agg: 上一次的聚合结果
curr: 代表本次聚合的元素
*/
//第一次执行的时候 agg=2 curr=5 agg+curr=7
//第二次执行的时候 agg=7 curr=1 agg+curr=8
//第三次执行的时候 agg=8 curr=10 agg+curr=18
//第四次执行的时候 agg=18 curr=3 agg+curr=21
//第五次执行的时候 agg=21 curr=20 agg+curr=41
def reduceTest(): Unit ={
val list = List[Int](2,5,1,10,3,20)
val i = list.reduce(_+_)
println(i)
}
/**
* reduceRight对于加法的话和reduce没有区别 但对于减法还是有区别的
* 这个是从最后一个元素是agg
*/
def reduceRight(): Unit ={
val list = List[Int](2,5,1,10,3,20)
println(list.reduceRight(_ + _))
}
/**
* fold agg的初始值为fold第一个参数列表的值
*/
def foldTest(): Unit ={
val list = List[Int](2,5,1,10,3,20)
val i = list.fold(10)((agg, curr) => agg + curr)
println(i)
}
//foldRigth
def foldRightTest(): Unit ={
val list = List[Int](2,5,1,10,3,20)
println(list.foldRight(10)((curr, agg) => curr + agg))
}
}
8、队列
1、不可变队列
1、创建方式: Queue[元素类型](初始元素,...)
2、获取元素: 队列变量.dequeue() [生成一个新队列]
3、插入元素:
队列变量.enqueue(元素)
4、删除元素: 队列变量.dequeue()
package com.zhijm.Day04
import scala.collection.immutable.Queue
object $16_ImmutableQueue {
def main(args: Array[String]): Unit = {
val queue = Queue[Int](1, 4, 6, 8)
// 添加元素
val queue1 = queue.+:(4)
println(queue1)
val queue3 = queue.:+(77)
println(queue3)
// 添加多个元素
val queue2 = queue.++(List(2, 3, 6, 78))
println(queue2)
val queue4 = queue.++:(List(8, 5, 4, 3))
println(queue4)
// 可以添加单个数据,也可以添加多个数据
val value = queue.enqueue(1)
val value2 = queue.enqueue(33)
println(value)
println(value2)
println(queue)
println(queue.enqueue(List(2, 3, 4, 5)))
// 获取数据
println(queue.dequeue._1)
}
}
2、可变队列
1、创建方式: mutable.Queue[元素类型](初始元素,...)
2、获取元素: 队列变量.dequeue() [修改本身队列]
3、插入元素:
队列变量.enqueue(元素)
4、删除元素: 队列变量.dequeue()
package com.zhijm.Day04
import scala.collection.mutable
/**
* 可变队列
*/
object $19_MutableQueue {
def main(args: Array[String]): Unit = {
val queue = mutable.Queue[Int](1, 2, 4, 56)
// 获取数据
val value = queue.dequeue()
println(value)
println(queue.dequeue())
// 添加数据
println(queue.+:(23))
println(queue.:+(44))
queue.+=(33)
println(queue)
queue.+=:(44)
println(queue)
// 添加多个数据
val queue1 = queue.++(List(3, 4, 6))
println(queue1)
queue.++=(List(3,6,7))
println(queue)
}
}
9、并行集合[将集合用多线程进行操作]
1、将普通集合转成并行集合: list.par
package com.zhijm.Day04
/**
* 并列集合
*/
object $21_PairList {
def main(args: Array[String]): Unit = {
val list = List[Int](2, 4, 5, 6, 7)
list.foreach(x=>{
println(Thread.currentThread().getName)
println(x)
})
println("&"*23)
// 多线程打印
list.par.foreach(x=>{
println(Thread.currentThread().getName)
println(x)
})
}
}
8、模式匹配
1、语法:
变量 match{
case 条件1 => 操作
case 条件2 => 操作
case 条件3 => 操作
case _ => 其他情况
}
package com.zhijm.Day05
import scala.io.StdIn
/**
* 模式匹配语法
* 变量 match {
* case 值 =>
* 匹配后的逻辑
* case 值 =>
* 匹配周的逻辑
* case _ =>
* 都不匹配的逻辑
* }
*/
object $01_Math01 {
def main(args: Array[String]): Unit = {
val word = StdIn.readLine()
word match {
case "李白"=>println(s"$word")
case "hadoop"=>println(s"$word")
case _=>println("无法匹配")
}
}
}
2、守卫[case后加一个if判断条件]
变量 match{
case 条件1 if 布尔表达式=> 操作
case 条件2 if 布尔表达式=> 操作
case 条件3 if 布尔表达式=> 操作
case _ => 其他情况
}
package com.zhijm.Day05
import scala.io.StdIn
/**
* 守卫
* 模式匹配语法
* 变量 match{
* case 值 if 布尔表达式=>匹配的逻辑
* case 值 if 布尔表达式=>匹配的逻辑
* case 值 if 布尔表达式=>匹配的逻辑
* case =>不匹配的逻辑
* }
*
* 模式匹配都是有返回值的
*/
object $02_Math_If {
def main(args: Array[String]): Unit = {
val word = StdIn.readLine()
val result = word match {
case x if x.contains("hello") => {println(s"${x}")
20}
case y if y.contains("hadoop") =>{println(s"$y")
10}
case x if x.contains("good") => {println(s"${x}")
24}
case _ => println("啥都不匹配")
}
println(result)
}
}
3、匹配类型:
1、匹配基本类型
变量 match{
case 变量名:类型1 => 操作
case _:类型2 => 操作
case 变量名:类型3 => 操作
case _ => 默认条件
}
如果匹配条件在=>不需要使用变量,变量可以用_代替
2、匹配常量
变量 match{
case 值1 => 操作
case 值2 => 操作
case 值3 => 操作
case _ => 操作
}
3、匹配数组:
arr match{
case Array(x) => 匹配数组只有一个元素
case Array(x,y,z) => 匹配数组有三个元素
case Array(x,y,_*) => 匹配数组至少有两个元素
case Array(x:String,y:Int,z:Boolean,_*) => 匹配数组至少有三个元素,前三个元素的类型分布为String,Int,Boolean
case _ => ...
}
package com.zhijm.Day05
/**
* 数组的模式匹配
*/
object $04_Match_Array {
def main(args: Array[String]): Unit = {
val array = Array[Any](35, "jj", 88)
array match {
case Array(a,b,c)=>
println(s"数组有三个元素,${a},${b},${c}")
case Array(35,_*)=>
println("数组的首为是35,后面有多少个元素不知道")
case Array(x:Int,y:String,c:Int,_*)=>
println("数组至少有三个元素,分别为int string,int类型")
case _=>println("没有其他的规则")
}
/**
* Array[Int] => new Int[]{..}
* Array[Stirng] => new String[]{}
* arr = new Object[]{}
*
* new String[]{}
*/
array match {
//case x:Array[Int]=>println("Array[Any]") 报错
case x:Array[Any]=>println("Array[Any]")
}
}
}
4、匹配列表
1、与Array匹配类型
list match{
case List(x) => 匹配列表只有一个元素
case List(x,y,z) => 匹配列表有三个元素
case List(x,y,_*) => 匹配列表至少有两个元素
case List(x:String,y:Int,z:Boolean,_*) => 匹配列表至少有三个元素,前三个元素的类型分布为String,Int,Boolean
case _ => ...
}
2、通过 :: 形式
Nil: 空列表
使用:: 的时候最后一个必须是列表
list match{
case x :: Nil => 匹配列表只有一个元素
case x :: y :: z :: Nil => 匹配列表有三个元素
case x :: y :: tail => 匹配列表至少有两个元素 [tail是一个列表]
case (x:String) :: (y:Int) :: (z:Boolean) :: tail => 匹配列表至少有三个元素,前三个元素的类型分布为String,Int,Boolean
case _ => ...
}
list、队列在匹配时候,如果是匹配类型,需要注意泛型擦除
val list =List[String](..)
list match{
case x:List[Int] => ..
case x:List[String] => ..
case _ => ..
}
此时会匹配到第一个条件,因为泛型擦除之后就时相当于匹配List
package com.zhijm.Day05
import scala.swing.event.AdjustingEvent
/**
* List集合的模式匹配
*/
object $05_Math_List {
def main(args: Array[String]): Unit = {
val list = List[Any]("hello",false,2.2,10,30,"hadoop")
/* list match {
case List(x)=>println(s"匹配list中只有一个元素的,${x}")
case List(x:String,y:Boolean)=>
println("匹配list至少有两个元素,这两个元素的类型为string 和boolean类型")
case List(x,y,z,_*)=>println(s"匹配List至少有三个元素${x},${y},${z} ")
case _=>println("没有其他的匹配规则")
}*/
//Nil代表空集合
//var n:List[Any] = Nil
// n=list
// println(n)
// :: 往Nil空集合添加数据
//var list2=0::2::4::Nil
// println(list2)
list match {
case x::Nil=>println(s"匹配list只有一个元素${x}")
case (x:String)::(y:Boolean)::tail=>println(s"匹配至少有两个元素 元素类型分别为 string boolean $tail")
case x::y::z::tail=>println(s"匹配list至少有三个元素${x} ${y} ${z} ${tail}")
}
// 泛型的特性:泛型擦除
/* Class<?> strListClass = new ArrayList<String>().getClass();
Class<?> intListClass = new ArrayList<Integer>().getClass();
// 输出:class java.util.ArrayList
System.out.println(strListClass);
// 输出:class java.util.ArrayList
System.out.println(intListClass);
// 输出:true
System.out.println(strListClass.equals(intListClass));*/
// 匹配的是List的字节码,也就是Class
list match {
case x:List[Boolean]=>println("List[Boolean]")
case x:List[String]=>println("List[String]")
case x:List[Any]=>println("List[Any]")
}
// set 和map的key是没有泛型擦除的
val map = Map[String, Int]("a" -> 12, ("b", 3))
map match {
case x:Map[String,String]=>println("Map[String,String]")
}
}
}
5、匹配元组
val tuple:(Any,Any,Any) = ("hello",1,"spark")
tuple match{
case (x,y,z) => ... //匹配元组的时候,元组有几个元素,匹配条件就必须是几个元素
case (x:String,y:String,z:String) => ..
}
package com.zhijm.Day05
object $06_MathType {
def main(args: Array[String]): Unit = {
val tuple = ("zhangsan", 20, "shenzhen")
tuple match {
// case (name:String,_:Int,_:String)=>println(s"name:$name")
case (name,_,_)=>
println(s"name:$name")
}
var school=List(
("宝安中学",("小学一班",("1001","zhangsan",20))),
("宝安中学",("小学一班",("1002","lisi",22))),
("宝安中学",("小学一班",("1003","wangwu",23)))
)
// 取出学生姓名 这种方法辨识清楚,需要写注释才知道表达的是什么
println(school.map(_._2._2._2))
//用匹配的方式进行取值
val list = school.map(line => {
line match {
case (schoolname, (classname, (sid, name, age))) => name
}
})
println(list)
// 简化版
val list1 = school.map {
case (schoolname, (classname, (sid, name, age))) => name
}
println(list1)
}
}
6、匹配对象和样例类
1、样例类:
语法: case class 类名([val/var] 属性名,[val/var] 属性名,..)
创建样例类对象: 类名(参数,..)
2、样例对象:
语法: case object object名称
创建样例对象: object名称
3、样例类可以用来模式匹配
case class Person(name:String,age:Int)
val p = Person("zhangsan",20)
p match{
case Person(x,y) => ...
}
package com.zhijm.Day05
import scala.beans.BeanProperty
/**
* 样例类(声明样列类,底层自动生成unapply ,apply方法)
* 语法:case class 类名([val/var] 属性名:属性类型)
* 样例对象(一般用于枚举)
* 语法:case object object名称
*/
case class Person(@BeanProperty name:String, @BeanProperty val age:Int)
trait SEX
case object Man extends SEX
case object Woman extends SEX
class Student(var name:String,val age:Int)
object Student{
def apply(name: String, age: Int): Student = new Student(name, age)
def unapply(arg: Student): Option[(String, Int)] = {
if (arg==null)
None
else
Some((arg.name,arg.age))
}
def math01(sex:SEX): Unit ={
println("===========")
}
}
object $07_Math_Object {
def main(args: Array[String]): Unit = {
// 样例类的使用
val person = Person("zhangsan", 26)
println(person.age)
println(person.getName)
// 样列对象
Student.math01(Man)
// 用样例类=>模式匹配
person match {
case Person(name,age)=>println(s"age:$age")
}
//不用样例类需要声明unapply方法
val student = Student("lisi", 23)
student match {
case Student(name,age)=>println(s"name:$name")
}
}
}
4、普通类如何像样例类一样进行模式匹配
需要在伴生对象中定义unapply方法,将对象的属性抽取出来
class Person(val name:String,val age:Int)
object Person{
def unapply(p:Person):Option[(String,Int)] = {..}
}
val person = new Person("lisi",30)
person match{
case Person(name,age) => ..
}
7、变量声明的模式匹配
val (name,age) = ("zhangsan",20)
val Array(x,y,_*) = Array(1,2,3,4,5)
val x :: y :: z :: tail = List(1,2,3,4,5)
8、for表达式的模式匹配
一般是指map for表达式的匹配
for( (k,v) <- map)
9、偏函数:
不使用match关键字的模式匹配称之为偏函数
1、语法:
val func:PartialFunction[IN,OUT] = {
case 条件1 => ..
case 条件2 => ..
case 条件3 => ..
..
case _ => ..
}
IN泛型: 函数的入参类型
OUT泛型: 函数的返回值的类型
package com.zhijm.Day05
/**
* 元组的匹配
*/
object $08_Math_Param {
def main(args: Array[String]): Unit = {
val tuple = math01(2, 3)
// 模式匹配的方式
tuple match {
case (x,y,z)=>println(z)
}
// 简写的 直接匹配返回值元组的每一个元素
val (x,y,z) = math01(1, 5)
println(x)
println(y)
println(z)
println("list")
// 类似的其他的数据类型也可以
val List(_,_,g,_*) = List(2, 3, 4, 6, 7)
println(g)
println("array")
val Array(a,b,c) = Array("张三", "李白", "杜甫")
println(a,b,c)
println("map")
val map = Map[String, Int]("zhangsan" -> 23, ("libai", 24))
for ((k,v)<-map)println(k,v)
for (i<-map)println(i)
}
def math01(x:Int,y:Int) ={
println(s"${x} ${y}")
("*"*x,"+"*y,s"${x}+${y}=${x+y}")
}
}
package com.zhijm.Day05
/**
* 偏函数:[不适用Match的模式匹配]
* var func:PartialFunction[IN,OUT]={
* case..=>..
* }
*/
object $09_Math_PartialFunction {
def main(args: Array[String]): Unit = {
var func:PartialFunction[Any,Int]={
case x:String=>
println("String")
10
case y:Int=>
println("Int")
20
case _=>
println("other")
23
}
val i = func("ddd")
println(i)
// 偏函数的使用场景
val school = List(
("宝安中学",("小学一班",("1001","zhangsan",20))),
("宝安中学",("小学一班",("1002","lisi",22))),
("宝安中学",("小学一班",("1003","wangwu",23)))
)
var function1:PartialFunction[(String,(String,(String,String,Int))),String]={
case (schoolname,(classname,(sid,name,age)))=>name
}
for(i<-school){
println(function1(i))
}
/*val list = school.map({
case (schoolname, (classname, (sid, name, age))) => name
})
println(list)*/
}
}
9、异常
scala中异常的处理方式:
1、抛异常: 直接在方法中通过throw关键字抛出异常
2、捕获异常: try{..}catch{case e:Exception => ..} finally{..}
try{..}catch{case e:Exception => ..} finally{..}该异常处理方式一般在获取外部链接的时候使用,可以通过finally关闭外部资源
大多数时候都是使用:Try(代码).getOrElse(代码异常返回的默认值)
package com.zhijm.Day05
import java.sql.{Connection, DriverManager, PreparedStatement}
import scala.util.Try
/**
* scala中方法不可以抛出异常,没有throws关键字
* try{}catch{}finally{}只在一种的场景用到
* 使用外部链接的是有会用到
*/
object $10_Exception {
def main(args: Array[String]): Unit = {
// println(method01(3, 0))
//method02()
/*val value = method03(16,8)
value match {
case Left(x)=>println(x)
case Right((e,y))=>println(y,e.getMessage)
case _=>println("没有结果")
}
if(value.isLeft)
println(value.left.getOrElse("没有值"))*/
// 获取某个年龄的时候有些输出缺失了,导致获取的时候可能出现异常
var list=List[String](
"1,zhangsan,20,shenzhen",
"lisi,30,shanghai",
"2,wangwu,30,shanghai"
)
// 手动过滤掉
/*
val list1 = list.map(line => {
val arr = line.split(",")
// 第一种做法
try {
arr(2).toInt
} catch {
case exception: Exception => 0
}
})
println(list1.filter(_ != 0))*/
// 使用Try类 然后通过filter过滤出成功的结果
/* println(list.map(Line => {
val value = Line.split(",")
var age: Try[Int] = Try(value(2).toInt)
age
}).filter(_.isSuccess).map(_.get))*/
/* println(list.map(line => {
val value = line.split(",")
Try(value(0).toInt)
}).filter(_.isSuccess).map(_.get))*/
//println(Try(1 / 0).getOrElse("除数为零"))
val triedInt = Try(1 / 0)
println(triedInt.getOrElse("除数为零"))
}
// try{}catch{使用模式匹配}finally{}
def method01(a: Int, b: Int): Int = {
try {
if (b == 5) throw new Exception("bbb")
a / b
} catch {
case e: Exception =>
println(e.getMessage)
0
} finally {
println("无论怎么样都执行到的")
}
}
/**
* scala 连接mysql try{}catch{case e:Exception=>}finally{资源的关闭}
*/
def method02(): Unit = {
var connection:Connection=null
var statement:PreparedStatement=null
try {
//1 加载数据库驱动
classOf[com.mysql.jdbc.Driver]
// 获取连接
connection=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test","root","root")
var sql=
"""
|select *
|from score
|""".stripMargin
// 创建 statement
statement=connection.prepareStatement(sql)
val result = statement.executeQuery()
while (result.next()){
print(result.getString(1)+" ")
print(result.getString(2)+" ")
print(result.getString(3))
println()
}
} catch {
case e: Exception => println(e.getMessage)
}
finally {
// 资源关闭
statement.close()
connection.close()
}
}
/**
* 将正常的结果封装在Left中
* 将有异常的结果封装Right中
* 使用的的是有可以用模式匹配的方法得到结果
* val value = method03(16,8)
* value match {
* case Left(x)=>println(x)
* case Right((e,y))=>println(y,e.getMessage)
* case _=>println("没有结果")
* }
*也可以直接获取正常的运行结果,过滤异常的结果
* if(value.isLeft)
* println(value.left.getOrElse("没有值"))
*
* @param a
* @param y
* @return
*/
def method03(a:Int,y:Int): Either[Int, (Exception, Int)] ={
try{
Left(a/y)
}catch {
case exception: Exception=>
Right(exception,y)
}
}
}