一、Scala简介
1、Scala简介
面向对象和面向函数式编程的一门编程式语言
静态类型,效率更高,避免bug
运行在JVM和脚本中
可以直接访问java类库
2、优点
简洁 性能好 可以直接访问java类库 spark底层便是用scala编写的
scala和java最终都是同一编译成.class文件
Scala的环境部署
IDEA 中创建Scala项目
二、Scala语法
2.1 数据类型
*在Scala中真正一切皆对象,包括基本数据类型,所以数据类型首字母都大写
Any是一切数据类型的超类
Nothing 是一切数据类型的子类
Int Float Double Byte Long Short String Char...
2.2 变量的定义
注:val 定义的变量不可二次赋值
var 定义的变量可以二次赋值
变量定义的时候就需要赋值
变量定义:
var/val 变量名:数据类型 = 值
数据类型一般省略(会自动推导)
var/val 变量名 = 值
类型转换:
toDouble
---调用方法--用于同级变量
比如 Int转 Double
asInstanceOf[String]
--强制类型转换
可用于不同级
比如:val a :Any=10
a.asIntanceOf[Double]
变量取值:
一种是直接取
另一种比较常用:s" $name $age"
def main(args: Array[String]): Unit = {
val name="zss"
val age:String="80"
var sal=1000.98
val aa =1 to 10
val age2 = age.toInt
val str=name+" "+age+" "+sal
println(s"$name 的年龄为: $age2 工资为:$sal")
println(str)
}
2.3 流程控制
2.3.1 if
if 的使用跟java基本一致
特殊出在于:if() {} 这是一个代码块,而代码块的最后一行是该代码块的返回值
例如:判断各个年龄段
def main(args: Array[String]): Unit = {
val arr=Array[Int](10,30,50,60,90)
val r = new Random()
val num = r.nextInt(arr.length)
var age=arr(num)
if(age<20){
println(s"年龄为:$age --青年")
}else if(age<50){
println(s"年龄为:$age --中年人")
}else{
println(s"年龄为:$age --老年人")
}
println(";;;;;;;;;;;;;;;;;;;;;;;;;;;")
val a=30
val b=if(a<20){
"a<20"
}else{
"a>=20"
}
println(b)
}
2.3.2 for
/*
i <- 1 to 10 则代表将1-10赋值给i
i <- 1 until 10 则代表将1-9赋值给i
1、遍历数组
2、99乘法表
3、嵌套循环 简便写法:for中直接写层级循环
for(i<-1 to 9;j<- 1 to i)
4、守卫模式:for中写入判断条件
for (elem <- arr2 if elem<60 && elem >20) {println(elem)}
5、推导式 yield
可以收集满足条件的元素,并且对元素进行再处理
*/
def main(args: Array[String]): Unit = {
//两种方式遍历数组
val arr=Array[String]("a","b","c","d")
//方式一:类似增强for
for (elem <- arr) { println(elem) }
println(";;;;;;;;;;;;;;;;;;;")
//方式二:索引
for(i <- 0 until arr.length){ println(arr(i)) }
//99乘法表
for(i<- 1 to 9){
for(j<- 1 to i){
print(s"$j * $i ="+i*j+" ")
if(i==j){
println()
}
}
}
println(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;")
//嵌套循环 简便方式
for(i<-1 to 9;j<- 1 to i){
print(s"$j * $i ="+i*j+" ")
if(i==j){
println()
}
}
println(";;;;;;;;;;;;;;;;;;;;;;;")
//守卫模式:在循环中加入条件判断,提高效率,不满足条件的不进入循环
val arr2=Array[Int](10,20,30,40,50,90)
for (elem <- arr2 if elem<60 && elem >20) {println(elem)}
for (elem2 <- arr2 if elem2%2==0) {println("偶数:"+elem2)}
}
推导式 yield
可以收集满足条件的元素,并且对元素进行再处理
def main(args: Array[String]): Unit = {
//找出数组中的字符串数据,然后转大写,打印出来
val arr= Array[Any]("lisii","liqingi","lixiani",11,34)
val array = for (elem <- arr if elem.isInstanceOf[String]) yield elem
for (elem <- array) {
println(elem.asInstanceOf[String].toUpperCase)
}
val strings = ( for (elem <- arr if elem.isInstanceOf[String]) yield elem.asInstanceOf[String].toUpperCase ).toList
println(strings)
}
2.3.3 while
while的使用与java一样
def main(args: Array[String]): Unit = {
var a=1
while(a<10){
println(a)
a+=1
}
println(";;;;;;;;;;;;;;;")
var b=1
do{
println(b)
b+=1
}while(b<10)
}
2.4方法
方法的定义:
def 方法名(参数1:类型,参数2:类型) 返回值类型={ 方法体 }
其中:无参数的时候,参数的括号可以省
可以不写返回值类型,会自动推导 直接写 =
方法体的最后一行是方法的返回值
方法的调用:
若是在object类中写的方法,由于是静态方法,直接类名调用
若是在calss类中写的方法,需要new 对象,通过对象来调用方法
//无参 无返
def show1={
println("hello ")
}
//有参 有返
def show2(x:Int,y:Int,z:Int)={
x+y*10+z
}
//可变参数--相当于数组
def show3(name:String,x:Int*)={
var sum=0
for (elem <- x) {
sum+=elem
}
println(s"$name : $sum")
}
//方法的调用
def main(args: Array[String]): Unit = {
show1
val i = show2(1, 2, 3)
println(i)
show3("zss",1,2,3,4)
}
三、 函数
3.1 函数的定义与使用
函数的定义
(参数1:类型,参数1:类型)=>{处理逻辑,和返回值}
def main(args: Array[String]): Unit = {
//函数的调用
val sum=(x:Int,y:Int)=>(x+y)
val sum2:(Int,Int)=>Int =(x,y)=>(x+y)
//函数的调用
val i = sum(1, 2)
val i1 = sum2(10, 20)
println(i)
println(i1)
}
3.2高阶函数
3.2.1 函数作为方法的参数
使函数更加灵活,使用时再写具体的逻辑
高阶函数(高阶方法)
方法中只做方法的声明(数据类型的声明)
在调用方法的时候再写上具体的逻辑
object Dmeo7 {
//在方法的参数位置,加上一个参数,这个参数是函数的数据类型声明,方法体中并为给出处理的逻辑,只是说处理时要用到哪个参数
def method(a:Int,b:Int,f:(Int,Int)=>Int) ={
f(a,b)
}
def method2(x:String,y:String,mm:(String,String)=>String)={
mm(x,y)
}
def method3(a:String,b:Int,f:(String,Int)=>String)={
f(a,b)
}
def method5(x:Int,y:String,f:(Int,String)=>String)={
f(x,y)
}
def main(args: Array[String]): Unit = {
val sum = method(10, 20, (a, b) => a + b)
println(sum)
//调用方法的时候再写具体的处理逻辑
val str = method2("aa", "bb", (a, b) => a + "--" + b)
println(str)
//(x, y) => x + ":" + y 这个也成为匿名函数
val str1 = method3("wbb", 30, (x, y) => x + ":" + y)
println(str1)
val str2 = method5(10, "wwt", (x, y) => x + "--" + y.toUpperCase)
println(str2)
}
}
//二分查找的方法
def binarySerch(arrs:Array[Int],order:Int):Int={
if(arrs.length==0){println("数组为空")}
var begin =0
var end = arrs.length-1
while(begin<=end){
var middle =(begin+end)/2
if(arrs(middle)>order){
end=middle-1
}else if(arrs(middle)<order){
begin=middle+1
}else{
println(s"目标数的索引为:$middle")
return middle
}
}
return -1
}
def main(args: Array[String]): Unit = {
val arr=Array[Int](10,20,30,33,54,60,90)
val index = binarySerch(arr, 10)
println(index)
}
3.2.2 函数作为方法的返回值
对数据进行连续性处理 闭包
def method(x:String,y:String)={
(z:String)=>(z+x+y)
}
def main(args: Array[String]): Unit = {
val f = method("aa", "bb")
val res = f("cc")
println(res)
// 闭包 函数引用了外部的变量
val str = method("aa", "bb")("--cc")
println(str)
}
3.2.3 偏函数
偏函数:对集合中的数据进行过滤
--简写形式
def main(args: Array[String]): Unit = {
val arr = Array("java", "sql", "js", "scala", 23, 20,true)
//简写形式1
val list = arr.collect({ case x: String => x.toUpperCase }).toList
println(list)
//简写形式2--数组为Any,从中只要Int类型
def m:PartialFunction[Any,Int]={
case x:Int => x*100
}
val res = arr.collect(m).toList
println(res)
}
3.3 隐式
3.3.1 隐式变量
隐式:有种偷偷的引用的意思
柯里化:方法的参数列表有多个
隐式:implicit
隐式变量:偷偷的引用
1)对于隐式变量,若直接给值,则用所给的
2)若没给参数,则从上下文去找符合条件的隐式变量,若有则直接引用过来,若无,则看有没有导 包
3)若有导包,则也可以引用过来,若导包也没有,则--必须报错
implicit val name="zss"
def meth(x:Int)(implicit y:String)={
x*100+"--"+y
}
def main(args: Array[String]): Unit = {
//柯里化方法,要给两个参数列表
val res = meth(11)("hello")
println(res)
//这里只给了一个参数,
// 由于另外一个参数是隐式参数,而恰好上下问中有一个同类型的隐式变量,于是便偷偷的引用 过来了
//import com.doit.day2.revise.Demo2_function1._
val res2 = meth(11)
println(res2)
}
3.3.2 隐式函数
隐式函数
类似隐式变量,在函数前面加上关键字implicit--上下文寻找,去导包中寻找
object Demo3_yinshi2 {
def meth(x:Int,y:String)(implicit f:(Int,String)=>String)={
f(x,y)
}
//隐式函数
implicit val ff=(x:Int,y:String)=>x*100+"--"+y
def main(args: Array[String]): Unit = {
//可以直接给出函数的实现
val res1 = meth(10, "hello")((a, b) => a * 10 + "--" + b)
println(res1)
//利用隐式函数--不用给出函数了,从上面偷偷的引用过来了
val res2 = meth(10, "hahaha")
println(res2)
}
}
----隐式函数,用来加强类
class Demo1 {
def add(x:Int,y:Int)={
x+y
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
//注意 :在类的后面() 构造器
class Demo2 (demo1: Demo1){
def sub(x:Int,y:Int)={
x-y
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
object Test {
/*
new Demo2(demo1)---这个是在建Demo2类的时候参数写的Demo1
方法m 的作用是产一个参数:Demo1 --->将其变为Demo2
相当于将Demo1 加强了,不仅有Demo1自己的方法,还可以使用Demo2的方法
*/
implicit def m(demo1: Demo1):Demo2={
new Demo2(demo1)
}
def main(args: Array[String]): Unit = {
val demo1 = new Demo1
val res = demo1.add(10, 20)
val res2 = demo1.sub(10, 20)
println(res2)
}
}
3.3.3 隐式类
隐式类:可用于增强其他的类
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
class Demo1 {
def add(x:Int,y:Int)={
x+y
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
object Demo2 {
//隐式类--只需要把 需要加强的类添加到 类的构造器的参数里 来就行了
implicit class RichDemo1(demo:Demo1){
def concat(x:String,y:String)={
x+y
}
}
def main(args: Array[String]): Unit = {
//在创建Demo1的对象时,便会发现Demo1还在一个隐式类的构造器参数里,所以便把那个类的方 法一起引用过来了
val demo = new Demo1
val res1 = demo.add(10, 20)
val res2 = demo.concat("hello", "word")
println(res1)
println(res2)
}
}
四、面向对象
2.1 class和object
class中的内容是普通的内容 可以new对象
object中的内容是静态的 不用new
伴生关系
* 类是对象的伴生类
* 对象是类的伴生对象
* 可以互相访问彼此私有的内容 理解为:一体的
* 1) 伴生类和对象同时使用
* 2) 优先使用对象
* 3) 需要new 的时候使用class class中有构造器
伴生类和伴生对象
* 条件 1:在同一个源文件中,
* 条件 2:对象名和类名相同
*class Demo4 是伴生类
*object Demo4 是伴生对象
* 最大特点:可以互相访问私有变量
* */
class Demo4 {
private val name="hhh"
private val age=10
def add(x:Int,y:Int)={
x+y
}
def main(args: Array[String]): Unit = {
//伴生类也可以访问伴生对象的私有变量
println(Demo4.sal)
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
}
object Demo4{
private val sal=199.89
val addr="北京昌平沙河"
def main(args: Array[String]): Unit = {
//伴生对象,可以访问伴生类的私有变量
val demo = new Demo4
println(demo.age)
}
}
2.2 构造器
/*
*类的构造器:
* class类才有构造器
* object类没有构造器
*
* 主构造器:
* 当不给参数的时候,便是空参构造器
* 给了参数,便是带参构造器
* 参数用val/var 修饰,则可以作用在任何位置
* 若参数没有val/var 修饰,则只作用在本类
* 辅助构造器:
* def this(){}
* 辅助构造器必须调用其他的构造器
*
* */
class Demo4 (val id:Int,val name:String){
def this()={
this(100,"zss")
}
}
2.3 成员变量
/*
* 成员变量
* 对于可变变量,可以使用占位符“_”
* */
class Demo1 {
// 成员变量
val id = 1
var age:Int = 22
// 占位 var
var age2:Int = _
val addr:String = ""
var account:Int=_
}
2.4 代码块
/*
Author: Tao.W
D a te: 2021/7/19
Description:
构造代码块:写在类中(class) 每次创建对象的时候加载
静态代码块:写在静态类中(object) 加载类的时候加载一次,之后便不再加载
*/
class Demo2 {
{
println("构造代码块")
}
}
object Demo2Object{
{
println("静态代码块")
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
def main(args: Array[String]): Unit = {
new Demo2
new Demo2
new Demo2
Demo2Object
Demo2Object
Demo2Object
/* 结果:
构造代码块
构造代码块
构造代码块
静态代码块*/
}
2.5 修饰符
/*
Author: Tao.W
D a te: 2021/7/19
Description:
权限修饰:跟java类似
对于私有的成员变量:伴生对象可以访问,
若private后指定了包,则这个包下的所有类也可以访问
*/
class Demo3 {
private val name:String="zs"
val age=20
private [duiXiang] val sal=999.8
}
object Demo3{
val demo = new Demo3
demo.age
}
2.6 特质
1)Scala中的特质,很类似java中的接口
2)特质可以多实现:extend....with..实现了特质,便拥有了特质的一切内容(包括方法和成员属 性)
3)为了更加灵活,特质可以在创建对象的时候再实现
4)java中的接口可以写:
成员变量,抽象方法,和default修饰的普通方法
Scala中的特质可以写:
成员变量,抽象方法,和普通方法
在实现接口和继承特质的时候都必须实现抽象方法
trait T11 {
val name="zs"
def meth():Unit
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
trait T12 {
val age=20
def add(x:Int,y:Int):Int
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
/*
继承了T11和T12
实现这两个特质的抽象方法
同时也拥有了这两个特质的所有内容
*/
class T extends T11 with T12 {
def meth3={
println("helloWord")
}
override def meth(): Unit = {
println("hello")
}
override def add(x: Int, y: Int): Int = {
x+y
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
object Test2 {
def main(args: Array[String]): Unit = {
val t = new T
t.name
t.age
t.meth()
t.meth3
val res = t.add(10, 20)
}
}
在创建对象的时候再决定继承哪个特质:
class TT {
}
;;;;;;;;;;;;;;;;;;;;
/*
在创建对象的时候再继承:val tt = new TT with T11 with T12
*/
object Test3 {
def main(args: Array[String]): Unit = {
val tt = new TT with T11 with T12 {
override def meth(): Unit = {
println("灵活的继承特质")
}
override def add(x: Int, y: Int): Int = {
x*10+y
}
}
}
}
2.7 样例类
/*样例类:相当于javaBean类,用于封装对象
定义:case class (成员变量)
样例类:
1)重写了get、toString、hashcod()、equals
2)实现了序列化
3)创建了伴生对象,重写了apply方法,所以可以不写new
4)只有get方法,没有set方法,一次性赋值,不可更改
5)成员变量默认val修饰的
*/
// 成员变量默认val修饰的
case class Demo(name:String,age:Int,sal:Double)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
object Test {
//创建了伴生对象,重写了apply方法,所以可以不写new
val demo = Demo("zss", 10, 98.9)
demo.name
demo.age
println(demo.sal)
}
五、集合
5.1 数组Array
数组的定义
不可变数组:
val array = Array[String]("aa", "bb", "cc")
可变数组:
val arrayBuffer = ArrayBuffer[Any](1, 2, 3, "aa", "hello")
数组的遍历
def main(args: Array[String]): Unit = {
val array = Array[String]("aa", "bb", "cc")
val arrayBuffer = ArrayBuffer[Any](1, 2, 3, "aa", "hello")
//遍历:方式一,增强for
for (elem <- arrayBuffer) {println(elem)}
//遍历:方式二,索引
for(elem <- 0 to array.length-1){
println(array(elem))
}
//遍历:方式三,foreach
arrayBuffer.foreach(elem =>println(elem))
}
数组的排序
sorted:默认字典排序
sortBy:指定排序规则,字典排序--数字可以实现降序
sortWith:指定排序规则,比较万能
对于自定义类的排序:
sorted:需要类实现可排序
sortBy:可以指定排序字段
sortWith:可以指定排序字段,且可以指定升序降序
def main(args: Array[String]): Unit = {
val array = Array[String]("ll", "zz", "dd")
val arrayBuffer = ArrayBuffer[Int](1, 233, 36,23,10)
//sorted
val sorted = array.sorted
println(sorted.toList)
val sorted1 = arrayBuffer.sorted
println(sorted1.toList)
//sortBY
val array3 = array.sortBy(e => e)
println(array3.toList)
println(arrayBuffer.sortBy(e => -e).toList)
//sortWith
println(array.sortWith( (x, y) => x > y).toList )
println(arrayBuffer.sortWith((x, y) => x < y).toList)
}
对自定义类的排序
case class User(name:String, age:Int, sal:Double)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
def main(args: Array[String]): Unit = {
val users: Array[User] = Array[User](User("zss", 10, 900.9), User("ls", 89, 678.98), User("ww", 67, 5678.98))
//sortBy
val array = users.sortBy(user => user.age)
println(array.toList)
//sortWith
val array1 = users.sortWith((user1, user2) => user1.sal > user2.sal)
println(array1.toList)
//sorted
implicit def userOrder(user:User):Ordered[User]={
new Ordered[User] {
override def compare(that: User): Int = {
//可以更灵活的定义排序规则
if(user.name.equals(that.name)){
user.age-that.age
}else{
user.name.compareTo(that.name)
}
}
}
}
val sorted = users.sorted
println(sorted.toList)
}
5.1.1 不可变数组
/*
Author: Tao.W
D a te: 2021/7/19
Description:
数组:
max 求数组中元素的最大值
maxby(e=>e) 按自己的规则排序 用于自定义类
比如: maxby(user=>user.age)
filter(e=>e>3) 从数组中过滤出满足条件的元素
distinct :去除数组中的重复元素
reverse: 数组的反转
take(n):从第一个开始,取n个元素
*/
object Demo4 {
def main(args: Array[String]): Unit = {
val arr1: Array[Int] = Array[Int](1, 4, 6, 3, 9,5, 5, 8, 9)
//找最大
val max: Int = arr1.max
println(max)
//去重
val arr2 = arr1.distinct
println(arr2.toList)
//过滤
val arr3 = arr1.filter(e => e > 6)
println(arr3.toList)
//反转
val arr4 = arr1.sorted.reverse
println(arr4.toList)
}
}
使用flatten方法,对集合中的元素进行压平,扁平化(有种拆开的意思)
使用flatmap 相当于先map后再flatten
object Demo2 {
def main(args: Array[String]): Unit = {
val bufferedSource = Source.fromFile("E:\\work2\\mrdata\\word2\\input\\word.txt")
val lines: Iterator[String] = bufferedSource.getLines()
/*while(lines.hasNext){
val str = lines.next()
println(str)
}*/
//将·迭代器转为数组,数组中时每一行数据
val array: Array[String] = lines.toArray
//每一行数据切开后返回数组,然后map将每个数组收集起来,所以返回的时二维数组
val ss: Array[Array[String]] = array.map(e => e.split("\\s"))
//使用flatten方法,将二维数组扁平化,扁平成一维数组
val s: Array[String] = ss.flatten
s.foreach(e=>println(e))
println(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;")
//若将字符串数组再进行扁平化,则会将单词拆开,形成一个字符数组
val wo: Array[Char] = s.flatten
wo.foreach(e=>println(e))
println(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;")
//使用flatmap 相当于先map后再flatten
val word: Array[String] = array.flatMap(line=>line.split("\\s"))
word.foreach(word=>println(word))
}
}
5.1.2 可变数组
/*
Author: Tao.W
D a te: 2021/7/19
Description: 可变数组:数组的长度可变
定义:ArrayBuffer
方法:下面的操作都是对原数组进行的操作,会对原数组进行改变
* 1 remove(index) 删除指定位置的元素
* remove(index,cnt) 从index位置开始 删除cnt个元素
* 2 append(x:T *) 向数组的后面添加元素 .+=(x:T*)
* 3 insert(index , x:T*) 向集合中插入元素 后面的元素会向后移动
* 4 insertAll(index,集合) 将集合插入到指定的位置 后面的元素会向后移动
* 5 clear() 清空集合
* 6 +=(元素) 和append的功能一致
* 7 -=(元素*) 移除指定的元素
* 8 ++=(集合)
--------------------------
9 isEmpt
head last 取第一个和最后一个元素
10 take(number) 获取前number个元素
11 takeRight(number) 获取后number个元素
12 mkString(",") 将数组中的元素用“,”拼成字符串
13 :+ (元素) 将返回一个新数组
数组 ++ 数组 --相当于合并,将返回一个新数组
14 count(_<10)--统计满足条件的个数
14 update(index,newDate) 更新元素
14 isEmpt :判断是否为空
15 toBuffer 可以将不可变的数组变为可变的数组,返回一个新数组
toArray 可以将可变的数组变为不可变的数组,返回一个新数组
*/
object Demo5 {
def main(args: Array[String]): Unit = {
val arrBuffer = ArrayBuffer[Int](1, 3, 8, 54, 23, 6, 7, 6, 5, 5, 7)
//remove
arrBuffer.remove(1)
println(arrBuffer.toList)
arrBuffer.remove(1,3)
println(arrBuffer.toList)
//append
arrBuffer.append(11, 22, 33)
println(arrBuffer.toList)
//+=(元素) 相当于append
arrBuffer += (11, 22, 33)
println(arrBuffer.toList)
//-=
arrBuffer-=(54,7)
println(arrBuffer.toList)
//-=(Array(54,7))
arrBuffer.--=(Array(54,7,3))
println(arrBuffer.toList)
//insert(index,元素)
arrBuffer.insert(1,99,99)
println(arrBuffer.toList)
//insert(index,Array())
arrBuffer.insertAll(1,Array(88,88,88))
println(arrBuffer.toList)
//clear 清空元素
arrBuffer.clear()
println(arrBuffer.toList)
}
}
5.2 List集合
感觉跟数组区别不大:
List:不可变List:List
可变List:ListBuffer
find
append insert insertAll :+ ++
def main(args: Array[String]): Unit = {
//List定义
val list1 = List[String]("aa", "bb")
val list2 = "aa"::"bb"::"cc"::Nil
val list3 = ListBuffer[Int](1, 2, 3, 4)
//取值
list3(1)
// find
val option = list1.find(_.equals("bb"))
val res = option match {
case Some(value) =>value
case None => -1
}
println(res)
// append insert insertAll :+ ++
list3.append(2,4,6)
list3.insert(0,11,22)
list3.insertAll(0 , List(100,200,300))
list3.insertAll(0 , Array(100,200,300))
list3:+(11):+(12)
val newLIst = list1 ++ list2
}
5.3 Set 集合
set
最大特点:元素不重复(自动去重)、、无序(所以也没有索引)
不可变Set:set
可变Set:mutable.set
set2.remove(3)
* add(e) 添加元素 不能保证数据的位置 +=
* drop(n) 删除n个元素 返回新的Set集合
* +(e1,e2...)
def main(args: Array[String]): Unit = {
//set定义
val set1 = Set[Int](1, 2, 33, 33,33,44)
val mutableSet = mutable.Set[String]("aa", "vv", "hello")
println(set1)
println(mutableSet)
mutableSet.add("word")
println(mutableSet)
}
5.4 Map集合
//不可变map的定义
val map1: Map[String, Int] = Map(("aa", 1), ("bb", 2), ("cc", 3))
val map2 = Map(1 -> "aa", 2 -> "bb", 3 -> "cc")
//可变map的定义
val muMap = mutable.Map(("aa", 1), ("bb", 2), ("cc", 3))
//map的遍历
for (elem <- map1) {
val key=elem._1
val value=elem._2
println(key+":"+value)
}
for ((k,v) <- map2) {
println(s"$k : $v")
}
//只取key
for ((k,_) <- map2) {
println(s"$k")
}
//获得key集合和value集合
val keySet: Set[String] = map1.keySet
val values: Iterable[Int] = map1.values
put:添加元素,key相同会覆盖
get:获取元素
def main(args: Array[String]): Unit = {
val map1: Map[String, Int] = Map(("aa", 1), ("bb", 2), ("cc", 3))
val muMap = mutable.Map(("aa", 1), ("bb", 2), ("cc", 3))
muMap.put("gg",99)
muMap.put("gg",99)
//根据键找值
val option = muMap.get("jj")
val res = option match {
case Some(value) => value
case None => "无"
}
println(res)
}
Map的两个重要方法:
mapValues:只对map中的value进行操作,返回新的Map
def main(args: Array[String]): Unit = {
val map1: Map[String, Int] = Map(("aa", 1), ("bb", 2), ("cc", 3))
// mapValues:只对map中的value进行操作,返回新的Map
val newMap = map1.mapValues(_ * 10)
for (elem <- newMap) {
println(s"key:${elem._1} value:${elem._2}")
}
//遍历map,只对value进行处理,返回新的map
val map2 = for (elem <- map1) yield {
(elem._1, elem._2 * 100)
}
println(map2)
for (elem <- map2) {
println(s"key:${elem._1} value:${elem._2}")
}
}
5.5 Tuple 元组
* 元组: 是一种简单的数据组织结构 , 处理数据简洁
* 可以替代我们之间的JAVABean封装数据
* 1 使用._n取值 从1开始计数
* 2 元组中的元素个数不超过22个
* 3 元组中只有两个元素的时候称为对偶元组
4 嵌套元组
def main(args: Array[String]): Unit = {
//元组的定义
val tuple: (Int, Int, Int, String, String, Int) = (1, 2, 3, "a", "bb", 9)
//嵌套元组
val tt = ((1, "aa"), (23, "ff"), (90, 1))
//元组的取值
tuple._1
tt._1._1
//元组的遍历
tuple.productIterator.foreach(println)
tt.productIterator.foreach(println)
}
5.6 集合的方法
filter:过滤
object D_filter {
def main(args: Array[String]): Unit = {
val arr = Array(1,2,3,4,5,6,7,8,9,10)
//多个filter过滤
val array: Array[Int] = arr.filter(_ % 2 == 0).filter(_ > 4)
println(array.mkString("、"))
//获取每行中单词个数大于5的行数
var number=0
val map: Map[Int, String] = Source.fromFile("E:\\work2\\mrdata\\word2\\input\\word.txt")
.getLines()
.map(e => {
number += 1
(number, e)
})
.toMap
val map1 = map.mapValues(v => {
if(v.length > 2){
v
}
})
for (elem <- map1) {
println(s"${elem._1} ${elem._2}")
}
}
}
groupBy :按一定规则分组
def main(args: Array[String]): Unit = {
//获取每行中单词个数大于5的行数
Source.fromFile("E:\\work2\\mrdata\\word2\\input\\word.txt")
.getLines()
.flatMap(_.split("\\s"))
.toArray
.groupBy(word=>word)
.mapValues(_.length)
.toList
.sortBy(-_._2)
.foreach(println)
}
* 集合的交集 差集 并集 集合的类型和泛型尽量一致
* intersect 交集
* diff 差集
* union 并集 不去重
object D_union {
def main(args: Array[String]): Unit = {
// Seq
val ls = List("a" , "b" ,"c","d")
val arr = Array("c","d","e" , "f")
// 交集
val res: List[String] = ls.intersect(arr)
// 在前面集合中出现 在后面集合中没有出现的元素
val res2: List[String] = ls.diff(arr)
// 两个几个并集 不会去重
val res3: List[String] = ls.union(arr) //.distinct
val res4: List[String] = ls ++ arr
println(res)
println(res2)
println(res4)
}
}
* zip 拉链操作 对应位置的元素进行合并成对偶元组
* zipWithIndex
*/
object D_zip {
def main(args: Array[String]): Unit = {
val names = Array("zss","lss","ww","wbb")
val ages = Array(23,24,51,28,33)
val res = names.zip(ages)
val res2 = names.zipWithIndex
val res3 = names.zip(ages).zipWithIndex
println(res.toList)
println(res2.toList)
println(res3.toList)
}
}
剩下的方法:在文档中可以进行详细查看
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y76ZuBPH-1657706181584)(img\functions_1.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wcJPHl0Q-1657706181584)(img\functions_2.png)]
6.6.1 forEach
迭代遍历集合中的每个元素,对每个元素进行处理 ,但是没有返回值 ,常用于打印结果数据 !
val ls = List(1,3,5,7,9)
ls.foreach(println) // 打印每个元素
ls.foreach(println(_))// 打印每个元素
ls.foreach(x=>println(x*10)) // 每个元素乘以10 打印结果
ls.foreach(x=>print(x+" "))// 打印每个元素 空格隔开
6.6.2 map
适用于任意集合
注意Map集合的用法
map函数遍历每个元素处理返回原集合类型的新集合 , 也可以不返回数据
列表,数组,Map中都有map函数 元组中没有map函数
val arr = Array[String]("JAVA", "C++", "SCALA")
val ls = List(1, 3, 5, 7, 9)
val set = Set(1, 3, 5, 7)
val mp = Map[String, Int]("ZSS" -> 100, "LSS" -> 99)
// map函数遍历每个元素处理返回原集合类型的新集合
val new_arr: Array[String] = arr.map(x => x)
val new_list: List[Int] = ls.map(x => x)
val new_set: Set[Int] = set.map(x => x)
// Map集合使用map函数
val new_Map1: Map[String, Int] = mp.map({ case v: (String, Int) => (v._1, v._2 * 10) })
val new_Map2: Map[String, Int] = mp.map(e => (e._1, e._2 + 100))
// map函数也可以不返回数据
ls.map(println(_))
6.6.3 filter和filterNot
适用于 数组 List Map
filter返回符合自己条件的新的集合,filterNot返回不符合自己条件的新的集合
val ls: List[Int] = List.range(1,10)
ls.filter(x=>x%2==0)
val new_list: List[Int] = ls.filter(_ % 2 == 0)// _ 代表每个元素
new_list .foreach(x=>print(x+" ")) // 2 4 6 8
ls.filterNot(_%2!=1).foreach(x=>print(x+" ")) 1 3 5 7 9
每个元素进行过滤
val set = Set("spark" , "scala" , "c++" , "java")
val new_set: Set[String] = set.filter(_.startsWith("s"))
set.filter(_.length>3)
多条件filter进行条件过滤
val ls = "spark":: "scala" :: "c++"::"java"::1::2::12.34::Nil
// 过滤出选过滤出String类型的和Double类型的数据
ls.filter{
case i:String => true
case i:Int=>false
case i:Double=>true
}
连续使用多次filter进行条件过滤
// 连续使用多次filter进行条件过滤
val map = Map[String,Int](("zss" ,91),("zww",89),("zzx",92) , ("ww",23))
map.filter(_._1.startsWith("z")).filter(_._2>90)
6.6.4 collect
常于 数组 List Map
collect函数也可以遍历集合中的每个元素处理返回新的集合
def map[B](f: (A) ⇒ B): List[B]
def collect[B](pf: PartialFunction[A, B]): List[B]
主要支持偏函数
val ls = List(1,2,3,4,"hello")
// 主要支持偏函数
val new_list: List[Int] = ls.collect({case i:Int=>i*10})
new_list.foreach(x=>print(x+" "))//10 20 30 40
// collect实现filter和map特性
list.collect({ case i: Int => i * 10
case i: String => i.toUpperCase
}).foreach(println)
val new_list2: List[Int] = ls.map({case x:Int=>x*10})
new_list2.foreach(x=>print(x+" "))// 错误 hello (of class java.lang.String)
因为collect支持偏函数 , 所以我们可以使用collect实现filter和map的特性!!!
val res: List[Int] = List(1, 2, 3, 4, 5, 6,"hello").collect({case i:Int if i%2==0=>i*10})
res.foreach(println) // 40 60 是不是牛逼闪电??
6.6.5 min和max
适用于 数组 List Map
数组
val arr = Array(1,2,345,67,5)
arr.min
arr.max
arr.sum
List
val ls = List(1,2,345,67,5)
ls.min
ls.max
ls.sum
Set
val set = Set(1,2,345,67,5)
set.min
set.max
set.sum
map 默认按照key排序获取最大和最小数据
val map = Map[String,Int]("a"->10, "b"->99 , "c"->88)
// map默认按照key排序获取最大和最小数据
map.min //(a,10)
map.max //(c,88)
6.6.6 minBy和maxBy
适用于 数组 List Map
集合中的min和max可以获取任意集合中的最小和最大值 ,但是如果集合中存储的是用户自定义的类 , 或者是按照Map集合中的key,value规则排序的话就需要用户指定排序规则
map按照value取最大最小
val map = Map[String,Int]("a"->10, "b"->99 , "c"->88)
// map默认按照key排序获取最大和最小数据
// 指定map排序 按照value排序
map.maxBy(x=>x._2) //(b,99)
map.minBy(x=>x._2) //(a,10)
集合中存储的是用户自定义的类型
class User(val name:String ,val age:Int) {}
方式一 隐式转换
implicit def ordersUser(user:User)={
new Ordered[User] {
override def compare(that: User) = {
user.age.compareTo(that.age)
}
}
}
val ls = List(new User("zs",22),new User("ww",18) ,new User("tq",34))
println(ls.max.name)
println(ls.min.name)
方式二:
println(ls.maxBy(x => x.age).name)
6.6.7 sum
适用于 数组 List Set
求集合中的所有元素的和 ,下面三种集合类型常用
val arr = Array(1,2,345,67,5)
arr.sum
val ls = List(1,2,345,67,5)
ls.sum
val set = Set(1,2,345,67,5)
set.sum
6.6.8 count
适用于 数组 List Map
def count(p: ((A, B)) => Boolean): Int
计算满足指定条件的集合元素数量
val arr = Array(1,2,345,67,5)
arr.count(_>5) // array list set 统用
val ls = List("hello" , "hi" , "heihei" , "tom")
ls.count(_.startsWith("h"))
ls.count(_.equals("hello"))
ls.count(_ == "hello")
// 忽略大小写
ls.count(_.equalsIgnoreCase("HELLO"))
// 统计符合条件的map元素的数量
val map = Map[String,Int]("a"->10,"ab"->10, "b"->99 , "c"->88)
map.count(x=>x._1.startsWith("a"))
map.count(_._2>10)
6.6.9 find
适用于 数组 List Map
查找符合要求的元素 , 匹配到就反回数据 ,最多只返回一个
Option中的数据要么是Some(T) 要么是None标识没有找到
val arr = Array(1,2,345,67,5)
val e: Option[Int] = arr.find(x=>x>1)
val ls = List("hello" , "hi" , "heihei" , "tom")
val res: Option[String] = ls.find(_.contains("a"))
if(res.isDefined){
println(res) //Some(hello)
println(res.get) //hello
}
val map = Map[String,Int]("a"->10,"ab"->10, "b"->99 , "c"->88)
val res_map: Option[(String, Int)] = map.find(x=>x._2>20)
if(res_map.isEmpty){
"没有匹配到内容"
}else{
// 打印数据
println(res_map.get)
}
6.6.10 flatten
适用于 数组 List
压平 将一个集合展开 组成一个新的集合
val arr = Array(1,2,345,67,5.23)
//val res1: Array[Nothing] = arr.flatten I数值了类型的无法压平
val ls = List("hello" , "hi" , "heihei" , "tom")
val res2: Seq[Char] = ls.flatten // 压成单个字符 因为字符串属于序列集合的一种
val map = Map[String,Int]("a"->10,"ab"->10, "b"->99 , "c"->88)
// map无法直接压平
//val flatten: immutable.Iterable[Nothing] = map.flatten
// 压平存储Map集合的list 获取Map中每个元素
val ls1 = List[Map[String,Int]](Map[String,Int]("a"->10,"ab"->10) , Map[String,Int]("jim"->100,"cat"->99))
ls1.flatten // List((a,10), (ab,10), (jim,100), (cat,99))
val res: List[Int] = List(Array(1,2,3),Array(4,5,6)).flatten
// 错误 注意压平的数据的类型
val res4 = List(Array(1,2,3),Array("hel",5,6)).flatten
6.6.11 flatMap
适用于 数组 List
map+flatten方法的组合 ,先遍历集合中的每个元素 , 再按照指定的规则压平, 返回压平后的新的集合
val ls = List("today is my first day of my life" , "so I feel so happy")
// map处理每个元素 就是处理每句话
ls.map(x=>println(x))
// 获取集合中的每个元素 获取两句话 然后再扁平成字符
ls.flatMap(x=>x)
// 指定扁平化的规则 按照空格压平 压平的规则
ls.flatMap(x=>x.split(" ")).foreach(println) // 获取到每个单词
map和flatMap处理数据详解
// 读取外部文件
val bs: BufferedSource = Source.fromFile("d://word.txt")
// 读取所有的数据行
val lines: Iterator[String] = bs.getLines()
// m遍历每行数据按照 \\s+ 切割返回一个新的迭代器
val words: Iterator[String] = lines.flatMap(_.split("\\s+"))
// 遍历迭代器 获取每个单词
words.foreach(println)
// 读取外部文件
val bs2: BufferedSource = Source.fromFile("d://word.txt")
// 获取所有的行数据
val lines2: Iterator[String] = bs2.getLines()
// 处理每行数据 切割单词后 每行返回一个数组 将所有的数组封装在迭代器中
val arrs: Iterator[Array[String]] = lines2.map(_.split("\\s+"))
6.6.12 mapValues
适用于 Map
mapValues方法只对Map集合的value做处理!
新版本的scala中已经废弃了这个方法 可以单独使用 map.values来单独处理map中所有的value数据!
6.6.13 sorted
适用于 数组 List Map
sorted 使用域简单的数字, 字符串等排序规则简答的集合进行排序 , 如果需要定制化排序建议使用sortBy 和 sortWith函数
List对数值
val list = List (1, 34 , 32 , 12 , 20 ,44 ,27)
// 返回排好序的list集合 默认从小到达排序
val sorted: List[Int] = list.sorted
对Array字符串
val arr = Array("jim" , "cat" , "jong" , "huba")
// 字符串默认按照先后排序
val sorted_arr: Array[String] = arr.sorted
对Map
val map = Map[String , Int]("aeiqi"->4 , "qiaozhi"->2 , "baji"->34)
// map集合也没有sorted 函数 只有转换成List或者Array集合 默认按照key字典先后排序
val sorted_map: Seq[(String, Int)] = map.toList.sorted
sorted_map.foreach(println)
implicit def ordersUser(user:User)={
new Ordered[User] {
override def compare(that: User) = {
that.age.compareTo(user.age)
}
}
}
val u1 = new User("wuji",34)
val u2 = new User("zhiruo",24)
val u3 = new User("zhoamin",44)
val u4 = new User("cuishan",64)
// Set集合中没有sorted方法 如果指定规则排序 转成成List集合
val set = Set(u1, u2 , u3 , u4)
// 默认按照用户指定的排序规则排序
val sorted_set = set.toList.sorted
sorted_set.foreach(println)
6.6.14 sortBy和sortWith
适用于 数组 List Map
var arr = Array(1, 11, 23, 45, 8, 56)
val arr1 = arr.sortBy(x => x) //ArraySeq(1, 8, 11, 23, 45, 56)
//按照数据倒序排列
val arr2 = arr.sortBy(x => -x) //(56, 45, 23, 11, 8, 1)
// 按照字典顺序排序
val arr3 = arr.sortBy(x => x.toString) //ArraySeq(1, 11, 23, 45, 56, 8)
// x 前面的元素 y 后面的元素
arr.sortWith((x, y) => x > y)
arr.sortWith((x, y) => x < y)
var list = List("hello", "cat", "happy", "feel")
// 字典顺序
list.sortBy(x => x)
// 执行排序
list.sortWith((x, y) => x > y)
list.sortWith((x, y) => x < y)
val map = Map("peiqi" -> 5, "jong" -> 3, "baji" -> 12)
map.toList.sortBy(x => x._1) //List((baji,12), (jong,3), (peiqi,5))
map.toList.sortBy(x => x._2) //List((jong,3), (peiqi,5), (baji,12))
// 指定key排序
map.toArray.sortWith((x,y)=>x._1>y._1)
map.toArray.sortWith((x,y)=>x._1<y._1)
//指定value排序规则
map.toArray.sortWith((x,y)=>x._2>y._2)
map.toArray.sortWith((x,y)=>x._2<y._2)
自定义类型在集合中的排序
val u1 = new User("wuji", 34)
val u2 = new User("zhiruo", 24)
val u3 = new User("zhoamin", 44)
val u4 = new User("cuishan", 64)
var arr = Array(u1, u2, u3, u4)
// 按照姓名字典排序
arr.sortBy(user => user.name)
//年龄小到大
arr.sortBy(user => user.age)
//数值类型的排序可以直接使用- 来倒序排列 年龄大到小
arr.sortBy(user => -user.age)
// 年龄大到小
arr.sortWith((user1, user2) => user1.age > user2.age)
// 年龄小到大
arr.sortWith((user1, user2) => user1.age < user2.age)
// 姓名字典升序
arr.sortWith((user1, user2) => user1.name < user2.name)
//姓名字典降序
arr.sortWith((user1, user2) => user1.name > user2.name)
6.6.15 partition和span
partition将数组按照指定的规则分组 ,适用于 数组 List Map
val list = List(1,2,3,4,5,6,7,8,9)
// 将集合根据条件分成两组返回一个存储集合的元组第一个集和实符合要求的元素
//(List(3, 6, 9),List(1, 2, 4, 5, 7, 8))
val res: (List[Int], List[Int]) = list.partition(x=>x%3==0)
//从第一个元素开始处理 配到不符合条件的就结束
list.span(_<3) // (List(1, 2),List(3, 4, 5, 6, 7, 8, 9))
val list2 = List("scala" , "is" , "option" , "fucntion")
// (List(scala, is, fucntion),List(option))
list2.partition(_.hashCode%2==0)
map集合******************************************
val map = Map("peiqi" -> 5, "jong" -> 3, "baji" -> 12)
// (Map(baji -> 12),Map(peiqi -> 5, jong -> 3))
val tuple: (Map[String, Int], Map[String, Int]) = map.partition(x=>x._1.contains("b"))
val tuple2: (Map[String, Int], Map[String, Int]) = map.partition(x=>x._2 >5)
6.6.16 grouped
将集合中的元素按照指定的个数进行分组
val list1 = List(1,2,3,4,5,6,7,8,9)
val list2 = List("scala" , "is" , "option" , "fucntion")
val map = Map[String,Int]("peiqi" -> 5, "jong" -> 3, "baji" -> 12)
// 两个元素分成一组 ,9个元素总共分成5组
val res: Iterator[List[Int]] = list1.grouped(2)
var i = 0
// 遍历每个元素
res.foreach(list=>{
i+=1
list.foreach(x=>println(x+"----"+i)) // 打印每个元素和它所对应的组
})
// 将map集合按照个数进行分组
val res2: Iterator[Map[String, Int]] = map.grouped(2)
res2.foreach(i=>i.foreach(x=>println((x._1,x._2))))
6.6.17 groupBy
将集合中的数据按照指定的规则进行分组
序列集合
val list1 = List(1,2,3,4,5,6,7,8,9)
val list2 = List("scala" , "is" , "option" , "fucntion")
// 对序列数据进行分组
val res1: Map[Boolean, List[Int]] = list1.groupBy(x=>x>3) //HashMap(false -> List(1, 2, 3), true -> List(4, 5, 6, 7, 8, 9))
val res2: Map[Boolean, List[Int]] = list1.groupBy(x=>x%2==0)//HashMap(false -> List(1, 3, 5, 7, 9), true -> List(2, 4, 6, 8))
list2.groupBy(x=>x.hashCode%2==0)
//HashMap(false -> List(is, option, fucntion), true -> List(scala))
val res: Map[Boolean, List[String]] = list2.groupBy(x=>x.startsWith("s"))
键值映射集合分组
val map = Map[String,Int]("peiqi" -> 5, "jong" -> 3, "baji" -> 12)
val arr = Array(("cat",21),("lucy",33),("book",22),("jack",34))
// 按照key和value的内容分组
println(map.groupBy(mp => mp._1))
println(map.groupBy(mp => mp._2))
// 根据key 或者 value 分成两组 满足条件的和不满足条件的
println(map.groupBy(mp => mp._1.hashCode%2==0))
println(map.groupBy(mp => mp._2>2))
// 对偶元组集合 和map的分组方式是一样的
arr.groupBy(arr=>arr._1)
arr.groupBy(arr=>arr._2)
6.6.18 reduce
底层调用的是reduceLeft , 从左边开始运算元素
val list = List(1,3,5,7,9)
// 每个元素累加 从左到右相加
val res1: Int = list.reduce(_+_) // 25
//1-3)-5)-7)-9
val res2: Int = list.reduce(_ - _) // -23
val arr = Array("haha", "heihei", "hehe")
// x 前面的元素 y 后面的元素 实现集合中字符串的拼接
val res3: String = arr.reduce((x, y) => x + " " + y) //haha heihei hehe
// 键值对元素的
val map = Map(("shaolin",88),("emei", 77),("wudang",99))
//(shaolin emei wudang,264) key value分别做归约操作
val res4: (String, Int) = map.reduce((m1,m2)=>(m1._1+" "+m2._1 , m1._2+ m2._2))
6.6.19 reduceLeft和reduceRight
val list = List(1, 3, 5, 7, 9)
val arr = Array("a", "b", "c","d","e")
val map = Map(("shaolin",88),("emei", 77),("wudang",99))
// 执行顺序是 1+3)+5)+7)+9
val res1: Int = list.reduceLeft(_+_)
// 1-3)-5)-7)-9
val res01: Int = list.reduceLeft(_-_)
val res2: String = arr.reduceLeft((a1, a2)=>a1+","+a2)
val res3: (String, Int) = map.reduceLeft((m1,m2)=>(m1._1+" "+m2._1 , m1._2+ m2._2))
println(res1) //25
println(res2) //a,b,c,d,e
println(res3)//(shaolin emei wudang,264)
val res11: Int = list.reduceRight(_+_) // 25
// 执行顺序是 a,(b,(c,(d,e))) a2 右边的最后一个元素
val res12: String = arr.reduceRight((a1, a2)=>a1+","+a2)//a,b,c,d,e
val res13: (String, Int) = map.reduceRight((m1,m2)=>(m1._1+" "+m2._1 , m1._2+ m2._2))//(shaolin emei wudang,264)
// 5-(7-9)-->5-(7-9)-->3-(5-(7-9))-->1-(3-(5-(7-9)))
val res14: Int = list.reduceRight(_-_)
println(res14) // 5
println(res11) //25
println(res12) //a,b,c,d,e
println(res13)//(shaolin emei wudang,264)
// 字符串的拼接
arr.reduce(_ ++ _)
// 字符串的拼接
println(arr.reduce(_ ++"."++ _))
6.6.20 交集差集并集
val arr1 = Array(1, 3, 5, 7, 0)
val arr2 = Array(5, 7, 8, 9)
val res1: Array[Int] = arr1.intersect(arr2) // 交集 5 7
val res2: Array[Int] = arr1.diff(arr2) // 差集 1 3
// 单纯的合并两个元素中的数据
val res3: mutable.ArraySeq[Int] = arr1.union(arr2) // 1,3,5,7 ,5,7,8,9
// 在2.13.+中的union 被concat代替
val ints: Array[Int] = arr1.concat(arr2)
ints.foreach(println)
// 去除重复数据
val res4: mutable.ArraySeq[Int] = res3.distinct //,3,5,7,8,9
6.6.21 distinct和distinctBy
去除集合中的重复的元素 ,可以去除简单类型的数据, 也可以除去自定义的类型(底层依然是hashcode和equals)
val arr1 = Array("a", "a","ab","cat" ,"hellocat" ,"hicat")
val newarr: Array[String] = arr1.distinct
newarr.foreach(println)
条件去重
val arr1 = Array(new User("ls",21),new User("ls",22),new User("zss",21))
// 去除重名的重复数据
val res: Array[User] = arr1.distinctBy(x=>x.age)
res.foreach(x=> println(x.name))
6.6.22 zip
实现拉链式拼接, 只要操作的集合是迭代集合就可以拼接
val list1 = List("a" , "b" , "c" , "d")
val arr1 = Array(1,2,3,4)
val map = Map[String,Int]("aa"->11,"cc"->22,"dd"->33)
// 以两个迭代集合中少的一方为基准对偶拼接List((a,1), (b,2), (c,3))
val res: List[(String, Int)] = list1.zip(arr1)
//ArraySeq((1,(aa,11)), (2,(cc,22)), (3,(dd,33)))
val res2: Array[(Int, (String, Int))] = arr1.zip(map)
6.6.23 zipWithIndex
简单理解为 遍历集合中的每个元素 , 将每个元素打上对应的索引值 , 组成元组(element , index) 返回新的集合 !
val list1 = List("a" , "b" , "c" , "d")
val arr1 = Array(1,2,3,4)
val map = Map[String,Int]("aa"->11,"cc"->22,"dd"->33)
// List(((a,1),0), ((b,2),1), ((c,3),2), ((d,4),3))
list1.zip(arr1).zipWithIndex
//List((a,0), (b,1), (c,2), (d,3))
list1.zipWithIndex
6.6.24 fold,foldLeft 和foldRight
归约操作类似于reduce函数 ,但是fold函数中多出来一个初始值
val arr = Array("tom" , "cat" , "jim" , "rose")
// 遍历集合中的每个元素进行拼接 比reduce函数多出一个初始值
val res = arr.fold("hello")(_+" "+_)
val ls = List(1,3,5,7)
// 100+1)+3)+5)+7 底层调用的是 foldLeft
val res2 = ls.fold(100)(_+_) // 116
ls.foldLeft(100)(_+_) // 116
从右边开始运算 默认的值先参与运算进来
// 7-10)-->5-(-3)-->3-8 -->1-(-5)
val res01: Int = ls.foldRight(10)(_-_) //6
6.6.25 scan
一个初始值开始,从左向右遍历每个元素,进行积累的op操作
val arr = Array("cat" , "jim" , "tom")
// ArraySeq(hello, hello cat, hello cat jim, hello cat jim tom)
arr.scan("hello" )(_+" "+_)
val nums = List(1,2,3)
// List(10,10+1,10+1+2,10+1+2+3) = List(10,11,12,13)
val result = nums.scan(10)(_+_)
6.6.26 mkString
将集合中的每个元素拼接成字符串
val arr = Array("a", "b", "c")
val str = arr.mkString
arr.mkString(" ")
arr.reduce(_+_)
arr.reduce(_+" "+_)
6.6.27 slice,sliding
slice(from: Int, until: Int): List[A] 提取列表中从位置from到位置until(不含该位置)的元素列表, 起始位置角标从0开始
slice
val arr = Array("a", "b", "c" ,"d","e","f")
arr.slice(0 ,2) // res0: Array[String] = ArraySeq(a, b)
sliding
sliding(size: Int, step: Int): Iterator[List[A]] 将列表按照固定大小size进行分组,步进为step,step默认为1,返回结果为迭代器
val nums = List(1,1,2,2,3,3,4,4)
// 参数一 子集的大小 参数二 步进
val res: Iterator[List[Int]] = nums.sliding(2,2)
res.toList // List(List(1, 1), List(2, 2), List(3, 3), List(4, 4))
6.6.28 take,takeRight,takeWhile
take 默认从左边开始取
val arr = Array("a", "b", "c" ,"d","e","f")
// 从左边获取三个元素 组成新的数组集合
arr.take(3)
takeRight 默认从右边开始取
val nums = List(1,1,1,1,4,4,4,4)
val right = nums.takeRight(4) // List(4,4,4,4)
takeWhile
// 小于4 终止
nums.takeWhile(_ < 4)
val names = Array ("cat", "com","jim" , "scala" ,"spark")
// 从左到右遍历符合遇到不符合条件的终止 储存在新的集合中
names.takeWhile(_.startsWith("c"))