目录java
===sql
●Java中:编程
//数据类型 变量名 = 值; final int b = 2; b = 23; //错误!!! final修饰的变量不可变 int a = 1; a = 22;
●在Scala中:数组
//val/var 变量名:变量类型 = 变量值 val a:Int = 1 a =2 //错误!!!! val修饰的变量不能够被从新赋值,相似于Java中的final var b:Int = 1 b = 2
●说明数据结构
var声明的变量能够从新赋值app
val声明的变量不能够从新赋值,或称之为不可变变量/只读变量。至关于java里用final修饰的变量dom
●注意:函数式编程
Scala中变量声明类型能够省略,解析器会根据值进行推断函数
Scala中语句最后不须要添加分号oop
val和var声明变量时都必须初始化
为了减小可变性引发的bug,应该尽量地使用不可变变量val。(推荐使用val)
若是想在变量名、类名等定义中使用语法关键字(保留字),能够配合反引号:
val `val` = 123 //(符号为键盘上Esc下面的键)
●Type关键字
Scala 里能够经过type 关键字来声明类型。
type 至关于声明一个类型别名:
// 把String 类型用S 代替 type S = String val name: S = "bigdata" println (name)
●懒值
应用场景
当val被声明为lazy时,初始化将被推迟,只有当这个变量真正被使用到的时候,变量的赋值代码才会真正的执行
lazy适用于初始化开销较大的场景
●代码演示
package com.flyingAfish.baseTest object VariableDemo { def main(args: Array[String]): Unit = { val name:String = "fizz" //name = "jack ma" //错误,val修饰的变量不能被从新赋值 var money:Int = 8888 money = 565//var修饰的变量能够从新赋值 val age = 18 //:Int 类型能够省略,编译器会自动推断age的类型 //age = "fizz" //错误,由于scala是强类型 type str = String //type关键字能够给类型起别名 val animal:str = "fish" //当val被声明为lazy时,初始化将被推迟,只有当这个变量真正被使用到的时候,变量的赋值代码才会真正的执行 //lazy适用于初始化开销较大的场景 val msg1 = init() println("我是按顺序执行的") println(msg1) println("===============") lazy val msg2 = init() println("我先于init方法执行") println(msg2) } //定义一个方法,输出一句话并返回一个字符串 def init() ={ println("init方法执行了") "msg" } } /* init方法执行了 我是按顺序执行的 msg =============== 我先于init方法执行 init方法执行了 msg */
scala提供多种定义字符串的方式,咱们能够根据须要来选择最方便的定义方式。
●双引号
val/var 变量名 = "字符串"
●三引号
若是有大段的文本须要保存,就可使用三引号来定义字符串。例如:保存一大段的SQL语句。三个引号中间的全部字符串都将做为字符串的值。
val/var 变量名 = """字符串1字符串2"""
●使用插值表达式
scala中,可使用插值表达式来定义字符串,有效避免大量字符串的拼接。
val/var 变量名 = s"${变量/表达式}字符串" val/var 变量名 = s"""${变量/表达式}字符串"""
●代码演示
package com.flyingAfish.baseTest object StringDemo { def main(args: Array[String]): Unit = { val name = "fizz" val sql = """ |select * // | 竖条为编译器自动添加 |from table |where name = fizz """.stripMargin //.stripMargin 编译器自动添加 val sql2 = s""" //s 为编译器自动添加 |select * |from table |where name = ${name} """.stripMargin println(name) println(sql) println(sql2) } } /* fizz select * from table where name = fizz select * from table where name = fizz */
●数值类型
Scala和Java同样,有多种数值类型Byte、Char、Short、Int、Long、Float、Double类型和1个Boolean类型。
Boolean | true 或者 false |
---|---|
Byte | 8位, 有符号 |
Short | 16位, 有符号 |
Int | 32位, 有符号 |
Long | 64位, 有符号 |
Char | 16位, 无符号 |
Float | 32位, 单精度浮点数 |
Double | 64位, 双精度浮点数 |
String | 其实就是由Char数组组成 |
●继承体系
●Any
在scala中,全部的类,包括值类型,都最终继承自一个统一的根类型Any,Any类是根节点
Any中定义了isInstanceOf、asInstanceOf方法,以及哈希方法等。AnyVal和AnyRef都扩展自Any类。
isInstanceOf:是否继承自某类
asInstanceOf:强制类型转换
●AnyVal-全部值类型的基类,全部的值都是类类型都是AnyVal的子类
- scala.Double
- scala.Float
- scala.Long
- scala.Int
- scala.Char
- scala.Short
- scala.Byte
上面是数字类型。
还包括scala.Unit 和 scala.Boolean 是非数字类型。
●AnyRef-是全部引用类型的基类。
除了值类型,全部其余类型都继承自AnyRef
●Null
是全部引用类型的子类型,Null类只有一个实例对象,null,相似于Java中的null引用。null能够赋值给任意引用类型,可是不能赋值给值类型。
●Nothing
是全部类型的子类型。Nothing类型没有实例。它对于泛型结构是有用处的,举例:
空列表Nil的类型是List[Nothing],它是List[T]的子类型,T能够是任何类。
Nothing能够做为没有正常返回值的方法的返回类型,很是直观的告诉你这个方法不会正常返回,并且因为Nothing是其余任意类型的子类,他还能跟要求返回值的方法兼容。
●Unit
用来标识过程,也就是没有明确返回值的函数。
因而可知,Unit相似于Java里的void。Unit只有一个对象实例(),这个实例也没有实质的意义。
●注意
1.Scala并不刻意区分基本类型 和 引用类型,因此这些类型都是对象,能够调用相对应的方法。
2.每一种数值类型都有对应的Rich类型,如RichInt、RichChar等,为基本类型提供了更多的有用操做。(重要)
3.String直接使用的是java.lang.String类,另外在scala.collection.immutable.StringOps中还定义了更多的操做。在须要时String能隐式转换为StringOps,所以不须要任何额外的操做,String就可使用这些方法。
Scala中的+ - * / %等操做符的做用与Java同样,位操做符 & | ^ >> <<也同样。
●注意:
1.Scala中的操做符其实是方法
2.Scala中没有++、--操做符,须要经过+=、-=来实现一样的效果(由于++ -- 前置后置容易混淆)
3.+ - * / %是方法,那么就能够进行操做符重载,完成特殊的运算(也就是本身在类中定义+ - * / %方法表示特殊的运算)
●高级:
1)中置操做符,
//A操做符B 等同于 A.操做符(B) val a = 1 val b = 2 var c = a + b var d = a.+(b) //等同与上式
2)后置操做符,
A操做符 等同于 A.操做符,若是操做符定义的时候不带()则调用时不能加括号
math.random
3)前置操做符,
+、-、!、~等操做符 A等同于 A.unary_操做符。
var b = true b = !b b = b.unary_! //等同与上式
4)赋值操做符,
A操做符=B 等同于 A=A操做符B
a += 1 a = a + 1 //等同与上式
●代码演示
package com.flyingAfish.baseTest object OperatorDemo { def main(args: Array[String]): Unit = { var a = 1 var b = 2 val result = a + b println(result)//3 val result2 = a.+(b) //在Scala中运算符实际上是方法 println(result2)//3 //a++ //错误,在Scala中为了不混淆,不支持++ -- a += 1 //a = a + 1 println(a)//2 }
定义变量时可使用 {} 包含一系列表达式,其中{}块的最后一个表达式的值就是整个块表达式的值。
●代码演示
package com.flyingAfish.baseTest object E_BlockDemo { def main(args: Array[String]): Unit = { var a = 1 var b =2 var c = { a = a + b b = a + b var i = a + b i //注意:{}块表达式的最后一行是整个表达式的值 } println(c)//8 } }
Scala条件表达式的语法和Java同样,只是更加简洁,且Scala中if else表达式是有返回值的
●注意:
Scala中没有三元表达式
若是if或者else返回的类型不同,就返回Any类型
对于没有返回值的,使用Unit,写作(),至关于java中的void
●代码演示
package com.flyingAfish.baseTest object ConditionDemo { def main(args: Array[String]): Unit = { val sex1 = "male" val sex2 = "female" //if表达式有返回值 val result1:String = if(sex1 == "male"){ "男" }else{ "女" } println(result1) val result2:String = if(sex1 == "male") "男" else "女" println(result2) //若是返回值类型不一致,返回Any val result3:Any = if(sex2 == "male"){ "男" }else{ 0 } println(result3) //()表示没有返回值,即Unit,至关于Java中的void val result4:Unit = if(sex2 == "male"){ println("男") }else{ println("女") } println(result4)//() } }
在scala中,可使用for循环和while循环,但通常推荐使用for表达式,由于for表达式语法更简洁
●简单for循环:
for (变量 <- 表达式/数组/集合) {循环体}
for(i <- 1 to 10){println(i)} //循环打印1~10
●嵌套for循环
for (变量1 <- 表达式/数组/集合; 变量2 <- 表达式/数组/集合) {循环体}
for(i <- 1 to 9; j <- 1 to 9){ if(i >= j ) print(s"${j} * ${i} = ${j*i}") if(j == 9) println() }
●守卫
for表达式中,能够添加if判断语句,这个if判断就称之为守卫。咱们可使用守卫让for表达式更简洁。
for(i <- 表达式/数组/集合 if 表达式) {循环体}
for(i <- 1 to 10 if i % 3 == 0) println(i) //3,6,9
●for推导式(有返回值)
在for循环体中,可使用yield表达式构建出一个集合,咱们把使用yield的for表达式称之为推导式
便可以使用for推导式生成一个新的集合(一组数据)
//该for表达式会构建出一个集合 val res = for(i <- 1 to 10) yield i * 10 //10,20,30,40...
●注意:
while、for语句自己没有值,即整个while语句的结果是Unit类型的()
var n = 1; val result:unit = while(n <= 10){ n += 1 } println(result) println(n)
●代码演示
package com.flyingAfish.baseTest object LoopDemo { def main(args: Array[String]): Unit = { //1 to 10 ===> [1,10] val res1 = 1 to 10 //Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) //1 until 10 ===> [1,10) val res2 = 1 until 10 //Range(1, 2, 3, 4, 5, 6, 7, 8, 9) //1 to 10 ===> [1,10],步长为2 val res3 = 1 to 10 by 2 //Range(1, 3, 5, 7, 9) println(res1) println(res2) println(res3) //1.简单for循环 for(i <- 1 to 10) println(i) println("===========分割线==========") //2.嵌套for循环--传统写法 for(i <- 1 to 9){ for(j <- 1 to 9){ if(i >= j){ print(s"${j} * ${i} = ${j * i} \t") } } println() } println("===========分割线==========") //2.嵌套for循环--Scala骚气写法 for(i <- 1 to 9;j <- 1 to 9){ if(i >= j) print(s"${j} * ${i} = ${j * i} \t") if(j == 9) println() } println("===========分割线==========") //3.守卫 //需求打印1~10中3的倍数 for(i <- 1 to 10){ if(i % 3 == 0) println(i) } println("===========分割线==========") for(i <- 1 to 10 if(i % 3 == 0)) println(i) println("===========分割线==========") //4.for推导式 //需求把1~10中的每个数扩大10倍造成一个新的集合 //使用yield关键字能够生成一个新的集合 val col = for(i <- 1 to 10) yield i * 10 println(col)//Vector(10, 20, 30, 40, 50, 60, 70, 80, 90, 100) println("===========分割线==========") //5.注意:while循环没有返回值 var n =1 val result = while (n <= 100){ n += 1 n } println(n)//101 println(result)//() } }
def 方法名(参数名1: 参数类型1, 参数名2: 参数类型2) : 返回类型 = {方法体}
●语法细节
\1. 方法的返回值类型和return能够不写,编译器能够自动推断出来
\3. 若是方法没有返回值,返回Unit类型(相似于void,也能够不写)
\4. 返回值类型有多种状况则返回Any
\5. 带有默认值参数的方法,调用时,能够给定新值,也可使用默认值
\6. 能够经过参数名来指定传递给哪个参数,这样传递参数时就能够不按照顺序传递
\7. 方法没有参数,调用时能够省略(),若是定义时()省略,调用时则必须省略
\8. 可变参数使用 变量名: 类型* (相似Java的...)
●代码演示
package com.flyingAfish.baseTest object MethodDemo { def main(args: Array[String]): Unit = { val result: Int = factorial(3) println(result)//6 println(noReturnValue())//() //val resutl2: Int = haveDefaultParam(b=2)//102 //val resutl3: Int = haveDefaultParam(a=1,b=2)//3 //val resutl4: Int = haveDefaultParam(1,2)//3 val resutl5: Int = haveDefaultParam(b=2,a=1)//3 //println(resutl2) //println(resutl3) //println(resutl4) println(resutl5) noParam val sum: Int = multiParam(1,2,3,4,5)//15 println(sum) } //def 方法名(参数名1:参数类型,参数名1:参数类型):返回值类型 = {方法体} //1.方法的返回值类型和return能够不写,编译器能够自动推断出来 def omitReturnValue() ={ 1 } //2.对于递归方法,必须指定返回类型 //需求:求n的阶乘 ==> 10的阶乘=1*2*3...*10 == 10 * 9 * 8 ..... def factorial(n:Int):Int = { if (n == 1){ 1 }else{ n * factorial(n-1) } } //3.若是方法没有返回值,返回Unit类型(相似于void,也能够不写) def noReturnValue():Unit={ println("m3") } //4.返回值类型有多种状况则返回Any或者不写 val sex = "male" def multiReturnValue():Any={ if (sex == "male"){ "男" }else{ 0 } } //5.带有默认值参数的方法,调用时,能够给定新值,也可使用默认值 //6.能够经过参数名来指定传递给哪个参数,这样传递参数时就能够不按照顺序传递 def haveDefaultParam(a:Int=100,b:Int):Int={ println("a="+a) println("b="+b) a + b } //7.方法没有参数,调用时能够省略(),若是定义时()省略,调用时则必须省略 def noParam={ println("m7") } //8.可变参使用 变量名:类型* (相似Java的...) //定义了一个方法能够传递多个int值,并返回他们的和 def multiParam(args:Int*):Int={ var sum = 0 for (i <- args){ sum +=i } sum } }
●完整语法:
val函数名称 :(参数类型)=>函数返回值类型 = (参数名称:参数类型)=>函数体
val sum:(Int,Int)=>Int = (a:Int,b:Int)=>{a + b}
●简写语法:
val函数名称 = (参数名称:参数类型) => 函数体
val max = (a:Int,b:Int)=>{ if(a > b) a else b }
●符号解释
= 表示将右边的函数 赋给 左边的变量
=> 左面表示输入参数名称和类型,右边表示函数的实现和返回值类型
●方法:
和以前学习Java时理解的方法同样,是封装了完成某些功能的代码块,所属于某一个类或对象
●函数:
在Scala中,函数是头等公民,函数是一个对象,那么既然是对象的话,函数就能够赋值给变量 或者 看成参数被传递,还能够 使用函数打点调用方法
Scala中函数继承自FuctionN,带有一个参数的函数的类型是function1,带有两个是function2,以此类推
●证实函数是对象
●函数是对象,能够打点调方法
package com.flyingAfish.baseTest object FunctionDemo { def main(args: Array[String]): Unit = { //val函数名称 = (参数名称:参数类型) => 函数体 val add1 = (a:Int) => {a } val add2 = (a:Int,b:Int) => {a + b} val add3: (Int, Int, Int) => Int = (a:Int, b:Int, c:Int) => {a + b + c} println(add1)//<function1> println(add2)//<function2> println(add3)//<function3> //结论:函数是对象,有N个参数打印的时候就是functionN val str: String = add1.toString()//函数是对象,因此能够调用方法 println(str)//<function1> //函数通常用法 println(add2(3,2))//5 } }
●函数能够赋值给变量并将能够看成参数进行传递
定义一个函数,接收两个参数,返回两个数的和
定义一个方法,接收两个参数和一个函数,并在方法体中调用函数,将两个参数传递给函数
package com.flyingAfish.baseTest object FunctionDemo { def main(args: Array[String]): Unit = { //函数能够赋值给变量并将能够看成参数进行传递 //定义一个函数,接收两个参数,返回两个数的和 val add = (a:Int,b:Int) => a + b //证实了函数是对象,且函数能够赋值给变量 val result1: Int = operator(1,2,add) //证实了函数是对象,且函数能够看成参数进行传递 println(result1)//3 //函数的好处: //能够将咱们要进行的操做进行传递!!! //也就是函数式编程的核心思想:行为参数化!!! val result2: Int = operator(1,2, (a,b)=> a*b) println(result2) println("=======================") //再来体会一下:行为参数化!!! //val list = List(1,2,3,4,5) val list = 1 to 5 //val f = (i:Int) => println(i) //list.foreach((i:Int) => println(i)) //list.foreach(i => println(i)) //list.foreach(println(_)) list.foreach(println) } //定义一个方法,接收两个参数和一个函数,并在方法体中调用函数,将两个参数传递给函数 def operator(a:Int,b:Int,fun:(Int,Int)=>Int) ={ fun(a,b) } }
●方法能够转换成函数
证实方法无返回值也能够调用
Java里面方法无返回值不能调用
package com.flyingAfish.baseTest object I_FunctionDemo4 { def main(args: Array[String]): Unit = { println(fizz()) //() 证实函数五返回值也能够条用,打印的是空括号() println(fizz _) //下划线 _能够将方法变成函数 //<function0> } def fizz() = { } }
●定义方法:
def 方法名(参数名1: 参数类型1, 参数名2: 参数类型2) : 返回类型 = {方法体}
●定义方法简写法:
def 方法名(参数名1: 参数类型1, 参数名2: 参数类型2) = {方法体}
def 方法名 = {方法体}
●定义函数完整语法:
val函数名称 :(参数类型)=>函数返回值类型 = (参数名称:参数类型)=>函数体
●定义函数简写语法:
val函数名名称 = (参数名称:参数类型) => 函数体
●注意:
严格的来讲,函数与方法是不一样的东西。定义方式上也有不少的区别
可是在Scala中,函数自己是对象,方法能够经过下划线_转换为函数。
结论:在Scala中
方法能够转换为函数,函数本质上就是对象
函数式编程的核心思想、灵魂所在:行为参数化!
●集合分类-按照数据结构特色分
Scala的集合都扩展自Iterable特质(先理解为接口)
有三大类:Seq序列(List)、Set、Map映射
●集合分类-按照可变和不可变分(注意:这里的可变和不可变指的是集合的内容和长度,和以前的var/val有区别)
大部分的集合Scala都同时提供了可变和不可变的版本。
开发时建议Scala优先采用不可变集合(默认即为不可变),知足不了需求是再使用可变集合
●可变集合和不可变集合相应的包为:
不可变集合:scala.collection.immutable (默认)
可变集合: scala.collection.mutable
●注意
val和可变不可变
var和val指的是:变量可否被从新赋值
集合可不可变指的是:集合长度或内容可不可变
对于数组:
不可变数组Array:长度不可变,元素可变(定长数组)
可变数组ArrayBuffer:长度和里面的元素均可变(变长数组)(注意:Java里面数组长度不可变)
对于其余集合:
不可变集合immutable:长度和内容都不可变,若是调用添加或者删除方法,会产生新的集合,原集合不变
可变集合mutable:长度和内容均可变
总结:
开中优先使用不可变,若是知足不了需求再使用可变
●不可变集合(immutable )继承层次:
●可变集合(mutable)继承层次:
●不可变/定长数组:
val/var 变量名= new Array[T](数组长度)//scala.collection.immutable包下,不须要导包,默认就是 val/var 变量名 = Array(元素1, 元素2, 元素3...)
●可变/变长数组:
val/var 变量名 = ArrayBuffer[T]() //须要手动导入import scala.collection.mutable.ArrayBuffer包 val/var 变量名 = ArrayBuffer(元素1, 元素2, 元素3...)
●数组操做
指定分隔符 mkString
将数组转换成数组缓冲 toBuffer(打印Buffer能够看到数组内容)
根据索引获取元素 ()
添加元素 +=
删除元素 -=
追加一个数组到变长数组 ++=
往指定角标插入元素 insert
删除指定角标的元素 remove
定长=>>变长 toBuffer
变长=>>定长 toArray
多维数组 Array.ofDimDouble
●遍历数组
1.能够for循环直接遍历数组
2.能够遍历下标再根据下标获取元素
3.回忆一下生成指定范围的序列
0 to n 生成[0,n]
0 until n 生成[0,n)
●数组其余经常使用方法
在Scala中,数组上的某些方法对数组进行相应的操做很是方便!
sum求和
max求最大值
min求最小值
sorted排序
reverse反转
●代码演示
package com.flyingAfish.baseTest import scala.collection.mutable object ArrayDemo { def main(args: Array[String]): Unit = { val arr: Array[Int] = Array(5,6,7,1,2,3,4,8,9)//不可变 //不可变==>可变 val arr2: mutable.Buffer[Int] = arr.toBuffer //可变==>不可变 val arr3: Array[Int] = arr2.toArray //遍历 for(i <- arr) println(i) println("====================") //arr.foreach((i:Int)=>println(i)) //arr.foreach(i=>println(i)) //arr.foreach(println(_)) arr.foreach(println)//行为参数化 println("====================") //逆序 for(i <- arr.reverse) println(i) println("====================") //经过索引遍历 for(i <- 0 until arr.length) println(arr(i)) //统计 println(arr.sum) println(arr.max) println(arr.min) println(arr.reverse.mkString(",")) println(arr.sorted.mkString(","))//按照默认的排序规则排序-升序 println(arr.sortBy((i:Int) => -i).mkString(",")) //降序 println(arr.sortWith((x:Int,y:Int) => x > y).mkString(","))//降序 } }
元组也是能够理解为一个容器,能够用来存放各类相同或不一样类型的数据。例如:姓名,年龄,性别,出生年月。
元组的元素是不可变的。
●建立元组
使用括号来定义元组
val/var 元组 = (元素1, 元素2, 元素3....) val animal = ("fish","cat","dog") val world = ("fizz",34,animal,34.43)
使用箭头来定义元组(元组只有两个元素)
val/var 元组 = 元素1->元素2 //对偶/二元组是最简单的元组(k,v) val animal: (String, String) = ("fizz", "dgo") val dog: (String, Int) = "god" -> 3
●获取元组中的值
//使用下划线加脚标 ,例如 元组名._1 元组名._2 元组名._3 val animal: (String, String) = ("fizz", "dgo") val dog: (String, Int) = "dog" -> 3 val name: String = animal._1 val age: Int = dog._2
注意:元组中的元素脚标是从1开始的
●将对偶(二元组)组成的数组转换成映射(映射就至关于Java中的Map,后面会讲)
将对偶/二元组的集合转换成映射:
调用其toMap 方法
●遍历
能够调用元组的productIterator方法获取迭代器对象进行遍历
●代码演示
package com.flyingAfish.baseTest object TupleDemo { def main(args: Array[String]): Unit = { //使用括号来定义元组 //val/var 元组 = (元素1, 元素2, 元素3....) val t1: (String, Double, Int) = ("hadoop",3.14,110) //元组里能够存放不一样类型的元素 //使用箭头来定义元组(元组只有两个元素) //val/var 元组 = 元素1->元素2 //对偶/二元组是最简单的元组(k,v) val t2: (String, Int) = "age"->18 val t3 = ("age",18) println(t1) println(t2) println(t3) println(t1.getClass) println(t2.getClass) println(t3.getClass) //获取元素 println(t1._1) println(t1._2) println(t1._3) println("============") //val iterator: Iterator[Any] = t1.productIterator for(i <- t1.productIterator) println(i) //将二元组组成的集合转成map val ts = Array(("jack",60),("tom",70),("rose",80)) val map: Map[String, Int] = ts.toMap println(map)//Map(jack -> 60, tom -> 70, rose -> 80) } }
●高能预警
List操做的API方法和符号特别特别多,不用刻意去记,后续学习中会使用一些常见的,用的多了就掌握了!
●List介绍
列表是scala中最重要的、也是最经常使用的数据结构。在scala中,也有两种列表,一种是不可变列表、另外一种是可变列表
但都具有如下性质:
能够保存重复的值
有前后顺序
●不可变列表(默认)
import scala.collection.immutable._
建立方式1.使用List(元素1, 元素2, 元素3, ...)来建立一个不可变列表
val/var 变量名 = List(元素1, 元素2, 元素3...) val strings: List[String] = List("book","subject","car") val book: List[Any] = List("English", 32, "chinese", 300)
建立方式2.使用::方法建立一个不可变列表
val/var 变量名 = 元素1 :: 元素2 :: Nil val money: List[Int] = 34 :: 34 :: 344 :: Nil
注意:
使用::拼接方式来建立列表,必须在最后添加一个Nil表示空列表
●可变列表
import scala.collection.mutable._
建立方式1.使用ListBuffer元素类型建立空的可变列表
val/var 变量名 = ListBuffer[Int]() val fizz: ListBuffer[Int] = ListBuffer[Int]()
建立方式2.使用ListBuffer(元素1, 元素2, 元素3...)建立可变列表
val/var 变量名 = ListBuffer(元素1,元素2,元素3...) val personName: ListBuffer[Any] = ListBuffer("kashke",34,"wangzida")
●head和tail
在Scala中列表要么为Nil(Nil表示空列表)
要么是一个head元素加上一个tail列表。
//head为列表第一个元素,tail为列表除第一个元素外的元素列表 val list1 = List(1,2,3,4,5) println(list1.head)//1 println(list1.tail)//List(2, 3, 4, 5) val list = List(1) println(list)//List(1) println(list.head)//1 println(list.tail)//List()
●::操做符
:: 操做符是将给定的头和尾建立一个新的列表,原列表不变 :: 操做符是右结合的,如1 :: 5 :: 2 :: Nil至关于 1 :: (5 :: (2 :: Nil)) ==> List(1,5,2)
●可变列表操做
获取/更改元素(使用括号访问(索引值)) 添加元素(+=) 追加一个列表(++=) 删除元素(-=) 转换为List(toList) 转换为Array(toArray)
●扩展:list其余操做符(了解)
:: (x: A): List[A] 在列表的头部添加一个元素或列表 +: (elem: A): List[A] 在列表的头部添加一个元素 :+ (elem: A): List[A] 在列表的尾部添加一个元素 ++ [B](that: GenTraversableOnce[B]): List[B] 从列表的尾部添加另一个列表 ::: (prefix: List[A]): List[A] 在列表的头部添加另一个列表
●扩展:等价操做(了解)
val left = List(1,2,3) val right = List(4,5,6) //如下操做等价 left ++ right // List(1,2,3,4,5,6) right.:::(left) // List(1,2,3,4,5,6) //如下操做等价 0 +: left //List(0,1,2,3) left.+:(0) //List(0,1,2,3) //如下操做等价 left :+ 4 //List(1,2,3,4) left.:+(4) //List(1,2,3,4) //如下操做等价 0 :: left //List(0,1,2,3) left.::(0) //List(0,1,2,3)
●代码演示
package com.flyingAfish.baseTest object ListDemo { def main(args: Array[String]): Unit = { //●不可变列表 //val/var 变量名 = List(元素1, 元素2, 元素3...) val list1 = List(1,2,3,4,5) //val/var 变量名 = 元素1 :: 元素2 :: Nil val list2 = 1::2::Nil //List(1,2) //●可变列表 //val/var 变量名 = ListBuffer[Int]() import scala.collection.mutable.ListBuffer val list3 = ListBuffer[Int]() //val/var 变量名 = ListBuffer(元素1,元素2,元素3...) val list4 = ListBuffer(1,2,3,4) list3.append(1,2,3) println(list1) println(list2) println(list3)//ListBuffer(1, 2, 3) println(list4) //List(1, 2, 3, 4, 5) //List(1, 2) //ListBuffer(1, 2, 3) //ListBuffer(1, 2, 3, 4) println(list1.head)//1 println(list1.tail)//List(2, 3, 4, 5) val list = List(1) println(list)//List(1) println(list.head)//1 println(list.tail)//List() println("============") list3.remove(1)//根据索引删除 println(list3)//ListBuffer(1, 3) list3 += 4 list3 -= 1 val list5 = list3.toList val list6 = list3.toArray val list7 = 0 +: list3 println(list7)//ListBuffer(0, 3, 4) list7 //遍历 for(i <- list3) println(i) list3.foreach(println) } }
●说明
队列数据存取符合先进先出的策略
有 scala.collection.mutable.Queue 和 scala.collection.immutable.Queue
通常来讲咱们在开发中队列一般使用可变队列(特殊),其余都推荐使用不可变
●常见操做
enqueue入队/+=追加
dequeue出队
●代码演示
package com.flyingAfish.baseTest import scala.collection.mutable object DueueDemo { def main(args: Array[String]): Unit = { //队列在开发中通常使用可变队列 val q = mutable.Queue[Int]() q.enqueue(1) q.enqueue(2) q.enqueue(3) q += 4 q.+=(5) println(q)//Queue(1, 2, 3, 4 , 5) val i: Int = q.dequeue() println(i)//1 } }
●Set说明
Set表明一个没有重复元素的无序集合;即没法加入重复元素且不保证插入顺序的。
●不可变Set(默认)
import scala.collection.immutable._
1.建立一个空的不可变集,语法格式:
val/var 变量名 = Set[类型]() val movie = Set[String]()
2.给定元素来建立一个不可变集,语法格式:
val/var 变量名 = Set(元素1, 元素2, 元素3...) val fresh = Set("apple","pear","apricot")
●可变Set
import scala.collection.mutable._
格式相同,导包不一样
●Set操做
方法 | 描述 |
---|---|
def +(elem: A): Set[A] | 为集合添加新元素,并建立一个新的集合,除非元素已存在 |
def -(elem: A): Set[A] | 移除集合中的元素,并建立一个新的集合 |
def contains(elem: A): Boolean | 若是元素在集合中存在,返回 true,不然返回 false。 |
def &(that: Set[A]): Set[A] | 返回两个集合的交集 |
def &~(that: Set[A]): Set[A] | 返回两个集合的差集 |
def ++(elems: A): Set[A] | 合并两个集合 |
●代码演示
package com.flyingAfish.baseTest object SetDemo { def main(args: Array[String]): Unit = { //●不可变Set(默认) //val/var 变量名 = Set(元素1, 元素2, 元素3...) val set1 = Set(1,2,3,4,5,6,7) //●可变Set //格式相同,导包不一样 //val/var 变量名 = Set[类型]() import scala.collection.mutable._ val set2 = Set[Int]() set2.add(1) set2.add(2) set2.add(3) val set3 = set2 + 4 val set4 = set2 - 1 set2.remove(2) println(set2)//Set(1, 3) println(set3)//Set(1, 2, 3, 4) println(set4)//Set(2, 3) val set5 = set2 ++ set3 //并集 println(set5)//Set(1, 2, 3, 4) val set6 = set3 & set2 println(set6)//Set(1, 3)//交集 val set7 = set3 &~ set2//差集 println(set7)//Set(2, 4) //遍历和其余集合同样 } }
●说明
在Scala中,把哈希表这种数据结构叫作映射。类比Java的map集合
●不可变Map
import scala.collection.immutable.Map
格式一:使用箭头
val/var map = Map(键->值, 键->值, 键->值...) // 推荐,可读性更好 val hero = Map("fish"->"潮汐海灵","zeus"->"宙斯","baiqi"->"白起")
格式二:利用元组
val/var map = Map((键, 值), (键, 值), (键, 值), (键, 值)...) val subject = Map(("math","数学"),("English","英语"),("physics","物理"))
●可变Map
import scala.collection.mutable.Map
格式相同,导包不一样
●获取值
map(键) map.get(键) map.getOrElse(键,默认值)//根据键取值,若是取到了则返回,没取到返回指定的默认值
●修改值
map(键)=值
●增长值
map.put(键,值)
●代码演示
package cn.fizz.collection object MapDemo { def main(args: Array[String]): Unit = { //●不可变Map //●可变Map //格式相同,导包不一样 import scala.collection.mutable._ //格式一:使用箭头val/var map = Map(键->值, 键->值, 键->值...) // 推荐,可读性更好 val map1 = Map("tom"->60,"rose"->70,"jack"->80,"zhaosi"->100) //格式二:利用元组val/var map = Map((键, 值), (键, 值), (键, 值), (键, 值)...) val map2 = Map(("tom",60),("rose",70),("jack",80),("zhaosi",100)) map1.put("lily",90) map1.remove("tom") println(map1) println(map2) //根据key取值 //Option是None和Some的父类 //None表示空的,什么都没有 //Some表示里面有一个元素,在使用get就能够取出来 val op: Option[Int] = map1.get("zhaosi") println(op.get)//100 //直接使用get方法很差,若是没有指定的key,继续操做可能会报错 //val op2: Option[Int] = map1.get("zaosi") //println(op2.get) val v: Int = map1.getOrElse("zaosi",0) println(v)//0 val v2: Int = map1.getOrElse("zhaosi",0) println(v2)//100 println("==========================") //遍历 //1.经过key for(k <- map1.keySet) println(map1(k)) println("==========================") //2.直接遍历value for(v <- map1.values) println(v) println("==========================") //3.经过元组 for((k,v) <- map1) println(k+":"+v) println("==========================") //4.函数式的遍历+模式匹配 map1.foreach{ case (k,v) => println(k+":"+v) } } } -------------------------------------------------------------------- -----------------------java版本------------------------------------- -------------------------------------------------------------------- import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; public class MapDemo { public static void main(String[] args){ Map<String, Integer> map = new HashMap<>(); map.put("k1",1); map.put("k2",2); map.put("k3",3); map.put("k4",4); Set<String> set = map.keySet(); for (String k : set) { System.out.println(map.get(k)); } Collection<Integer> values = map.values(); for (Integer value : values) { System.out.println(value); } //开发的时候建议使用entrySet //由于entrySet拿出来的就是全部的kv,不须要在根据k去找v!!! Set<Map.Entry<String, Integer>> entries = map.entrySet(); for (Map.Entry<String, Integer> entry : entries) { System.out.println(entry.getKey() + ":"+entry.getValue()); } } }