Scala高级语法入门 (四) 一文彻底了解 Scala中的集合 多图详解

🙆‍♂️🙆‍♂️ 写在前面

​🏠​ 个人主页:csdn春和
📚 推荐专栏:更多专栏尽在主页!
JavaWeb专栏(从入门到实战超详细!!!)
SSM专栏 (更新中…)
​📖​ 本期文章:Scala高级语法入门 (四) 一文彻底了解 Scala中的集合
如果对您有帮助还请三连支持,定会一 一回访!🙋🏻‍♂️



Scala中的集合

简介

Scala的集合有三大类:序列Seq集Set映射Map,所有的集合都扩展自Iterable特质。对于几乎所有的集合类,Scala都同时提供了可变和不可变的版本

可变集合可以在适当的地方被更新或扩展。这意味着你可以修改,添加,移除一个集合的元素。

不可变集合类,相比之下,永远不会改变。不过,你仍然可以模拟添加,移除或更新操作。但是这些操作将在每一种情况下都返回一个新的集合,同时使原来的集合不发生改变,所以这里的不可变并不是变量本身的值不可变,而是变量指向的那个内存地址不可变

可变集合和不可变集合,在scala中该如何进行区分呢?我们一般可以根据集合所在包名进行区分:

1️⃣ scala.collection.immutable 不可变

2️⃣ scala.collection.mutablel> 可变

Scala 不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。类似于 java 中的 String 对象

可变集合,就是这个集合可以直接对原对象进行修改,而不会返回新的对象。类似 于 java 中 StringBuilder 对象

1、数组

1.1、不可变数组

1、基本语法

val arr1 = new Array[Int](10) // 方式一

(1)new 是关键字

(2)[Int]是指定可以存放的数据类型,如果希望存放任意数据类型,则指定 Any

(3)(10),表示数组的大小,确定后就不可以变化

val arr1 = Array(1, 2) // 方式二 使用的是伴生对象的apply方法

(1)在定义数组时,直接赋初始值

(2)使用 apply 方法创建数组对象

object Scala_Collection01_Array1 {
  def main(args: Array[String]): Unit = {
    // TODO 集合 数组 基本语法

    // TODO 1、定义数组
    val array = Array(1,2,3,4)

    println(array.mkString(","))  // mkString方法将集合中的元素转为字符串输出 参数为指定一个分隔符

    // TODO 2、修改数组中的值
    array(0) = 9
    array.update(3,7)  // 采用update方法修改元素
    println(array.mkString(","))


    println("***************************************")

    // TODO 3、遍历
    // 普通遍历
    for (i <- array) {
      println(i)
    }
    
  }
}

在这里插入图片描述

scala中提供了另外一种简化遍历的方法 foreach

在这里插入图片描述

// 简化遍历
def arrayForeach(i:Int): Unit ={
  println(i)
}
array.foreach(arrayForeach)

查看结果:

在这里插入图片描述

既然传递的参数是一个函数 那么我们就可以使用匿名函数 ,那么也可以使用匿名函数的至简原则来简化代码书写

// 简化写法
//    array.foreach((i:Int) => {println(i)}) // 完整写法
//    array.foreach((i:Int) => println(i))   // 省略{}
//    array.foreach((i) => println(i))      // 参数类型可推导出来 类型可以省
//    array.foreach(i => println(i))        // 参数只有一个 () 可以省略
array.foreach(println(_)) // 参数只出现一次 可以用_ 代替

2、基本操作

1、添加元素

// 2、添加元素
val ints1 = array1.+:(6)
val ints2 = array1.:+(6)

val array2 = Array(6, 7, 8, 9, 10)
// 将另一个数组添加到数组中
val ints3 = array1.++(array2) 
val ints4 = array1 ++ array2

// 比较内存地址
println(array1 eq(ints1))  // false
println(array1 eq(ints2))  // false

scala默认提供的集合都是不可变得,操作数据的时候会产生新的集合

2、常用方法

object Scala_Collection01_Array3 {
  def main(args: Array[String]): Unit = {
    // TODO Array的常用方法

    // 多维数组 ofDim
    val array: Array[Array[Int]] = Array.ofDim[Int](3, 2)
    array.foreach(list => println(list.mkString(",")))

    // 合并数组 concat
    val array1 = Array(1, 2, 3)
    val array2 = Array(4, 5, 6)
    val array3 = Array.concat(array1, array2)
    println(array3.mkString(","))

    // 创建指定范围的数组 range 前闭后开
    val array4 = Array.range(0, 2)
    println(array4.mkString(","))

    // 创建并填充指定数的数组 fill  数组里面全是-1
    val array5: Array[Int] = Array.fill[Int](5)(-1)
    println(array5.mkString(","))

  }
}

1.2、可变数组

可变数组的定义方式和不可变数组一样 使用的是ArrayBuffer进行定义

object Scala_Collection02_ArrayBuffer1 {
  def main(args: Array[String]): Unit = {
    // TODO 可变数组
    // 方式一:使用new关键字
    val buffer = new ArrayBuffer[Int]
    // 方式二:使用伴生对象声明
    //    val buffer = ArrayBuffer(1, 2, 3, 4)

    // 增加数据
    buffer.append(1, 2, 3, 4)

    // 修改数据
    buffer.update(0, 5)  // 5 2 3 4
    buffer(1) = 6

    // 删除数据
    val i: Int = buffer.remove(2) // 删除下标索引为2的元素  5 2 4
    buffer.remove(1, 2) // 删除下标索引为1起 删除两个元素 5

    // 查询数据
    println(buffer(0))  // 5

    // 循环集合
    for (i <- buffer) {
      println(i)
    }

    // 简化循环
    buffer.foreach(println)

  }
}

在可变数组中
使用 ++ 运算会产生新的数组
使用++= 不会产生新的数组

// 使用 ++ 运算符会产生新的集合数组
val buffer4: ArrayBuffer[Int] = buffer1 ++ buffer2
// 使用 ++= 运算符会更新之前的集合,不会产生新的数组
val buffer5: ArrayBuffer[Int] = buffer1 ++= buffer2
println( buffer1 eq buffer4 ) // false
println( buffer1 eq buffer5 ) // true

1.3、可变数组与不可变数组的相互转换

object Scala_Collection02_ArrayBuffer2 {
  def main(args: Array[String]): Unit = {
    // TODO 可变数组
    val buffer = ArrayBuffer(1,2,3,4)  // 可变数组
    val array = Array(4,5,6,7)   // 不可变数组

    // 将不可变数组转换为可变数组
    val buffer1: mutable.Buffer[Int] = array.toBuffer
    // 将可变数组转换为不可变数组
    val array1: Array[Int] = buffer.toArray
  }
}

scala也提供了将java集合转为scala集合的API

// java集合 <=> Scala集合

import scala.collection.JavaConverters._
val list: util.ArrayList[Nothing] = new util.ArrayList()
list.asScala.foreach(println) // java集合转为scala集合

val java: util.List[Int] = List(1, 2, 3, 4).asJava // scala集合转为java集合

2、集合的三大类

1、seq集合

list存放数据有序 可以放重复数据的集合,有序指的是插入顺序有序

不可变list

// Seq集合
val list = List(1,2,3,4)

// 增加数据
val list1: List[Int] = list :+ 1
println(list1 eq list)  // fasle
println(list1.mkString(","))

val list2: List[Int] = 1 +: list
println(list2.mkString(","))

println("*****************")

val list3: List[Int] = list.updated(1,5)
println(list eq list3)  // false  不可变集合 会产生新的集合
// Seq集合
val list1 = List(1, 2, 3, 4)

// 空集合
val list2: List[Nothing] = List()
val nil = Nil  // nil表示空集合
println(list2 eq nil)  // true

// 创建集合
val list3: List[Int] = 1 :: 2 :: 3 :: Nil  // 将 1 2 3 放入空集合中
val list4: List[Int] = list1 ::: Nil    // 将list拆分装入空集合

// 连接集合
val list5: List[Int] = List.concat(list3, list4)
println(list5.mkString(","))

// 创建一个指定重复数量的元素列表 fill
val list6: List[String] = List.fill[String](3)("a")
list6.foreach(println)

可变list

object Scala_Collection05_Seq2 {
  def main(args: Array[String]): Unit = {
    // TODO Seq可变list集合

    // 可变集合
    val buffer = new ListBuffer[Int]()

    // 增加数据
    buffer.append(1, 2, 3, 4)  // 1 2 3 4 

    // 修改数据
    buffer.update(1, 3)  // 改变自身   1 3 3 4
    val buffer1 = buffer.updated(1, 3) // 修改之后产生新的集合

    // 删除数据
    buffer.remove(2)   // 1  3 4
    buffer.remove(2, 2)  // 1 3

    // 获取数据
    println(buffer(1)) // 3 

    // 遍历集合
    buffer.foreach(println) // 1 3  

  }
}

相互转换

object Scala_Collection05_Seq3 {
  def main(args: Array[String]): Unit = {
    // TODO 可变list和不可变list的相互转化

    val buffer = ListBuffer(1, 2, 3, 4)
    val list = List(5, 6, 7, 8)

    // 可变集合转变为不可变集合
    val list1: List[Int] = buffer.toList
    // 不可变集合转变为可变集合
    val buffer1: mutable.Buffer[Int] = list.toBuffer
  }
}

2、set集合

数据无序且不可重复

数据无序:

val set = Set(1,2,3,4,5,6,7,8)

println(set)

在这里插入图片描述

不可重复:

val set = Set(1,2,3,4,1,2,3,4)

println(set)

在这里插入图片描述

不可变set

// 增加数据
val set3: Set[Int] = set1 + 5 + 6
val set4: Set[Int] = set1.+(6,7,8)
println( set1 eq set3 ) // false
println( set1 eq set4 ) // false
set4.foreach(println)
// 删除数据
val set5: Set[Int] = set1 - 2 - 3
set5.foreach(println)

val set6: Set[Int] = set1 ++ set2
set6.foreach(println)
println("********")
val set7: Set[Int] = set2 ++: set1
set7.foreach(println)
println(set6 eq set7)

可变set

object Scala_Collection06_Set1 {
  def main(args: Array[String]): Unit = {
    // TODO Set集合  可变set

    val set1 = mutable.Set(1,2,3,4)
    val set2 = mutable.Set(5,6,7,8)

    // 增加数据 add方法
    set1.add(5)

    // 添加数据 set中的update是对数据进行处理
    set1.update(6,true)
    println(set1.mkString(","))

    // 删除数据
    set1.update(3,false)
    println(set1.mkString(","))

    // 删除数据
    set1.remove(2)
    println(set1.mkString(","))

    // 遍历数据
    set1.foreach(println)

  }
}

集合取交集 差集

val set1 = mutable.Set(1, 2, 3, 4)
val set2 = mutable.Set(2,4, 5, 6, 7)

// 交集
val set3: mutable.Set[Int] = set1 & set2
println(set3.mkString(","))

// 差集
val set4: mutable.Set[Int] = set1 &~ set2
println(set4.mkString(","))

在这里插入图片描述

3、Map集合

Map(映射)是一种可迭代的键值对(key/value)结构。所有的值都可以通过键来获取。Map 中的键都是唯一的。

不可变啊Map

无序的:

/ map描述了一个数据无序 key不可重复的集合
// scala中的kv键值对非常特殊

val map = Map(
  "a" -> 1, "b" -> 2, "c" -> 3, "d" -> 4, "e" -> 5
)

println(map)

在这里插入图片描述

key不可重复

val map = Map(
  "a" -> 1, "b" -> 2, "c" -> 3, "d" -> 4, "e" -> 5,"a" -> 6
)

println(map)

在这里插入图片描述

基本语法:

 val map1 = Map( "a" -> 1, "b" -> 2, "c" -> 3 )
 val map2 = Map( "d" -> 4, "e" -> 5, "f" -> 6 )

 // 添加数据
 val map3 = map1 + ("d" -> 4)
 println(map1 eq map3) // false

 // 删除数据
 val map4 = map3 - "d"
 println(map4.mkString(","))

 val map5: Map[String, Int] = map1 ++ map2
 println(map5 eq map1)
 println(map5.mkString(","))

 val map6: Map[String, Int] = map1 ++: map2
 println(map6 eq map1)
 println(map6.mkString(","))

 // 修改数据
 val map7: Map[String, Int] = map1.updated("b", 5)
 println(map7.mkString(","))

 // 遍历数据
 map1.foreach(println)

基本操作:

val map1 = Map( "a" -> 1, "b" -> 2, "c" -> 3 )
val map2 = Map( "d" -> 4, "e" -> 5, "f" -> 6 )

// 创建空集合
val empty: Map[String, Int] = Map.empty
println(empty)

// 获取指定key的值 apply
val i: Int = map1.apply("c")
println(i)
println(map1("c"))

// 获取可能存在的key值  Option类型是专门为了解决空指针异常而设计的
val maybeInt: Option[Int] = map1.get("c")
// 判断key值是否存在
if ( !maybeInt.isEmpty ) {
    // 获取值
    println(maybeInt.get)
} else {
    // 如果不存在,获取默认值
    println(maybeInt.getOrElse(0))
}

// 获取可能存在的key值, 如果不存在就使用默认值
println(map1.getOrElse("c", 0))

可变map

// TODO Map集合 可变Map

val map1 = mutable.Map("a" -> 1, "b" -> 2, "c" -> 3)
val map2 = mutable.Map("d" -> 4, "e" -> 5, "f" -> 6)

// 添加数据
map1.put("d", 4)
val map3: mutable.Map[String, Int] = map1 + ("e" -> 4)
println(map1 eq map3)
val map4: mutable.Map[String, Int] = map1 += ("e" -> 5)
println(map1 eq map4)

// 修改数据
map1.update("e", 8)
map1("e") = 8

// 删除数据
map1.remove("e")
val map5: mutable.Map[String, Int] = map1 - "e"
println(map1 eq map5)
val map6: mutable.Map[String, Int] = map1 -= "e"
println(map1 eq map6)
// 清除集合
map1.clear()

4、tuple元组

在Scala语言中,我们可以将多个无关的数据元素封装为一个整体,这个整体我们称之为:元素组合,简称元组。有时也可将元组看成容纳元素的容器,其中最多只能容纳22个

// TODO Tuple 元祖

// 创建元组,使用小括号
val tuple = (1, "zhangsan", 30)

// 根据顺序号访问元组的数据
println(tuple._1)
println(tuple._2)
println(tuple._3)

// 迭代器
val iterator: Iterator[Any] = tuple.productIterator

// 根据索引访问元素
println(tuple.productElement(0))

// 如果元组的元素只有两个,那么我们称之为对偶元组,也称之为键值对
val kv: (String, Int) = ("a", 1)
val kv1: (String, Int) = "a" -> 1
println(kv eq kv1)

map的底层是对偶元组

// 如果元祖中的元素只有2个 称之为对偶元组 也可以称之为键值对
val kv = (1, "a")

val map = Map(
  (1, "a"), (2, "b"), (3, "c")
)

// 遍历
map.foreach(
  t => {println(s"${t._1} = ${t._2}")}
)

在这里插入图片描述

5、Queue

队列:Scala也提供了队列(Queue)的数据结构,队列的特点就是先进先出。进队和出队的方法分别为enqueue和dequeue。

object Scala_Collection09_Queue {
  def main(args: Array[String]): Unit = {
    // TODO Queue 队列

    val que = new mutable.Queue[String]()
    // 添加元素
    que.enqueue("a", "b", "c")
    val que1: mutable.Queue[String] = que += "d"
    println(que eq que1)
    // 获取元素
    println(que.dequeue())
    println(que.dequeue())
    println(que.dequeue())

  }
}

在这里插入图片描述

6、并行

Scala为了充分使用多核CPU,提供了并行集合(有别于前面的串行集合),用于多核环境的并行计算。

在这里插入图片描述

object Scala_Collection10_Par {
  def main(args: Array[String]): Unit = {
    // TODO 并行集合

    val result1 = (0 to 100).map{x => Thread.currentThread.getName}
    val result2 = (0 to 100).par.map{x => Thread.currentThread.getName}

    println(result1)
    println(result2)


  }
}

3、集合常用方法

3.1、常用方法

// TODO 集合中常用的方法

val array = ArrayBuffer(1,2,3,4,2,4,5)

// 1、集合长度
println(array.size)
println(array.length)

// 2、判断集合是否为空
println(array.isEmpty) // false

// 3、判断集合是否包含某个元素
println(array.contains(2)) // true

// 4、去重
println(array.distinct.mkString(",")) // 12345

// 5、集合反转
println(array.reverse.mkString(",")) // 5424321

// 6、将集合转为字符串
println(array.mkString(","))

// 7、集合循环遍历
array.foreach(println)

// 8、集合迭代器
println(array.iterator)

衍生集合

object Scala_Collection03_Method2 {
  def main(args: Array[String]): Unit = {
    // TODO 集合中常用的方法

    val array = ArrayBuffer(1,2,3,4)

    // TODO 从集合中获取部分数据
    // 1、获取第一个元素 集合头
    println(array.head) // 1
    // 2、集合尾
    println(array.tail) // (2,3,4)
    // 3、集合尾迭代器
    println(array.tails) // 迭代器
    // 4、最后一个元素 last
    println(array.last) // 4
    // 5、集合初始值
    println(array.init) // (1,2,3)
    // 6、集合初始迭代器
    println(array.inits)

    // TODO 取前几个元素
    println(array.take(2)) // 取前两个 1,2
    println(array.takeRight(2)) // 取后三个

    // TODO 丢弃前几个元素
    println(array.drop(1))  // 丢弃前一个元素
    println(array.dropRight(1)) // 丢弃后一个元素

  }
}

多数据集操作:

val list1 = List(1, 2, 3, 4)
val list2 = List(3, 4, 5, 6)

// 集合并集
println("union => " + list1.union(list2))  // 并集 合并在一起  12343456
// 集合交集
println("intersect => " + list1.intersect(list2)) // 交集 3,4
// 集合差集
println("diff => " + list1.diff(list2)) // 差集 去掉交集部分 1 2 

滑动滚动窗口:

在这里插入图片描述

// 滑动窗口
println(list1.sliding(2).mkString(","))
// 滚动(没有重复) 第二个参数称之为滑动步长
println(list1.sliding(2,2).mkString(","))

拉链操作

// 拉链操作
println("zip => " + list1.zip(list2))
// 数据索引拉链 自身和索引尽心拉链
println("zipWithIndex => " + list1.zipWithIndex)

3.2、计算函数

1、常用聚合函数
val array = ArrayBuffer(1,2,3,4)

// 1、求最大值
println(array.max)
// 2、求最小值
println(array.min)
// 3、求和
println(array.sum)
// 4、求乘积
println(array.product)

如果我们想要做其他运算操作呢?相除 相减

2、reduce

这里就需要我们自定义数据操作的方法,我们以相加为例

scala中提供了reduce集合简化规约的方法 传递的参数是一个函数

在这里插入图片描述

代码实现:

def reduceFun(x:Int,y:Int): Int ={
  x + y
}

println(array.reduce(reduceFun))

太复杂 这里我们就可以使用我们熟悉的匿名函数了

集合简化规约左和集合简化规约右

val array2 = Array(1,2,3,4,5)

// 集合简化规约左
println(array2.reduceLeft(_ - _)) // -13
// 集合简化规约右
println(array2.reduceRight(_ - _))  // 3 

查看底层源码

在这里插入图片描述

// 反转 [5,4,3,2,1]
// reduceleft y - x
// 1-(2-(3-(4-5))) = 3  所以结果为3
3、fold

集合和外部的数据做聚合操作

在这里插入图片描述

object Scala_Collection03_Method4 {
  def main(args: Array[String]): Unit = {
    // TODO 集合 计算函数 聚合函数

    val array = ArrayBuffer(1,2,3,4)
    val num = 5

    // 折叠 将集合外的数据 和集合内的元素做两两聚合

    // fold 底层调用的是foldLeft
    println(array.fold(num)(_ + _))

    // foldLeft
    // 5 [1,2,3,4] 
    // (((5-1)-2)-3)-4
    println(array.foldLeft(num)(_ - _)) // -5

    // foldRight
    // 反转 5 [4,3,2,1]
    //  1-(2-(3-(4-5))) = 3
    println(array.foldRight(num)(_ - _))  // 3

  	// scan 记录计算的过程
    println(array.scan(num)(_ - _))
    println(array.scanRight(num)(_ - _))

  }
}

3.3、功能函数

功能函数:由集合对象提供的函数执行自定义的功能

1、map
val array = ArrayBuffer(1,2,3,4)

// 需求 将集合中的数据+2  3,4,5,6

// map映射 传递一个函数类型的参数即可 做具体的操作
println(array.map(_ + 2))
println(array.map(_ * 2))
2、flatten

扁平化:将整体拆分成个体

// 扁平化只对最外层起作用
val array = ArrayBuffer(
  ArrayBuffer(1,2),ArrayBuffer(3,4)
)

println(array.flatten)

在这里插入图片描述

// 扁平化只对最外层起作用
val array = ArrayBuffer(
  ArrayBuffer(ArrayBuffer(1,2),ArrayBuffer(3,4)),
  ArrayBuffer(ArrayBuffer(5,6),ArrayBuffer(7,8))
)

println(array.flatten.flatten) // 调用两次

在这里插入图片描述

3、flattenMap

扁平化映射 相当于先map 再flatten

// 2、扁平化映射 先map 再flatten
val array1 = Array("java java scala spark","hello java scala spark")

// 需求 : 将字符串分解为一个一个的单词
println(array1.flatMap(str => str.split(" ")).mkString(","))

在这里插入图片描述

4、filter

过滤函数 可以对集合中没一个数据进行筛选过滤

val array2 = ArrayBuffer(1,2,3,4)
// 需求:留下 偶数
println(array2.filter(num => {
  num % 2 == 0
}))

// 至简原则
println(array2.filter(_ % 2 == 0))
5、groupBy
val array3 = ArrayBuffer(1,2,3,4)

// 奇数一组 偶数一组
println(array3.groupBy(_ % 2))

分组小练习:将首字母一样的分一个组

println("------------------------小练习-----------------------")

val strArray = ArrayBuffer("scala","spark","java","javascript")

println(strArray.groupBy(word => word.substring(0, 1)))
println(strArray.groupBy(word => word.charAt(0)))

在这里插入图片描述

6、sortBy

排序,通过指定的规则对每一条数据进行排序

val array4 = ArrayBuffer(1, 3, 2, 5, 7, 4)
// 通过指定的规则对数据进行排序 默认为升序
println(array4.sortBy(num => num))
// 降序 使用过函数的柯里化
println(array4.sortBy(num => num)(Ordering.Int.reverse)) // 降序

val array5 = ArrayBuffer("1", "22", "11", "2", "3")
println(array5.sortBy(s => s)) // 按照字典序 1 11 2 22 3
println(array5.sortBy(s => s.toInt)) // 按照数字排序 1 2 3 11 22

在这里插入图片描述

7、sortWith

自定义排序

// 自定义排序 按元素大小升序排序
println(list1.sortWith((x, y) => x < y))
// 自定义排序 按元素大小降序排序
println(list1.sortWith((x, y) => x > y))

在这里插入图片描述

  • 24
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 24
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值