Scala基础(三)

Scala-集合

简介

说明

  1. 集合三大类:序列(seq)、集(set)、映射(map),所有的集合都拓展自iterable特质
  2. 对于几乎所有的集合类,Scala都提供了可变和不变的版本,分别位于scala.collection.immutable(不可变集合)、scala.collection.mutable(可变集合)两个包下。

不可变集合

Scala中的不可变集合,由于Scala的基本单元是对象,因此这的不可变指代的是集合对象不可变,每次改变原对象不变,会返回一个新的对象

可变集合

可变集合是直接对原本的对象做修改,不会返回新的对象。

通性操作

  • 所有集合通用的添加[+:、:+、+=、+=:、++、++:、++=、++=:]/删除[-、-=、--、--=]方法区别:
    • 带+与带-的区别:
      • 带+是添加元素
      • 带-是删除元素
    • 一个+/-与两个+/-的区别:
      • 一个+/-是添加/删除单个元素
      • 两个+/-是添加/删除一个集合所有元素
    • 带冒号与冒号在前、冒号在后的区别:
      • 冒号在前是将元素添加在集合最末尾
      • 冒号在后是将元素添加在集合最前面
      • 带冒号是将元素添加在集合最末尾
    • 带=与不带=的区别:
      • 带=是修改集合本身
      • 不带=是生成新集合,原集合没有改变
    • update与updated的区别:
      • update是修改集合本身元素
      • updated是生成新集合,原集合元素没有改变

数组

不可变数组

通过new方式: new Array [ 元素类型 ] ( 数组的长度)

通过apply方法: Array[ 元素类型 ] ( 初始元素,... )<常用>

代码演示

    //1、通过new方式: new Array[元素类型](数组的长度)
    val arr = new Array[Int](5)
    println(arr.toList)

    //2、通过apply方法: Array[元素类型](初始元素,...)
    val arr2 = Array[Int](10,3,2,6,5)

    println(arr2.toList)

    //添加元素
    //添加单个元素
    val arr3 = arr2.+:(20)
    println(arr2.toList)
    println(arr3.toList)
    println(arr2)
    println(arr3)

    val arr4 = arr2.:+(30)
    println(arr4.toList)

    //添加一个集合所有元素
    val arr5 = arr2.++(Array(100,300,400))
    println(arr5.toList)

    val arr6 = arr2.++:(Array(100,300,400))
    println(arr6.toList)

    //删除

    //获取指定角标元素
    println(arr6(0))

    //修改指定角标元素
    arr6(0)=1000
    println(arr6.toList)

    for(element<- arr6){
      println(element)
    }

    //不可变数组转可变数组
    val arr11 = arr6.toBuffer
    println(arr11)

可变数组

通过new方式: new ArrayBuffer[ 元素类型 ] ()

通过apply方法: ArrayBuffer[ 元素类型 ] (初始元素,...)

代码演示

//通过new方式: new ArrayBuffer[元素类型]()
val arr1 = new ArrayBuffer[Int]()

//通过apply方法: ArrayBuffer[元素类型](初始元素,...)
val arr = ArrayBuffer[Int](10,3,2,6,7)

println(arr1)
println(arr)

//添加元素
//添加单个元素
val arr2 = arr.+:(30)

val arr3 = arr.:+(40)

println(arr2)
println(arr3)
println(arr)

arr.+=(50)
println(arr)

arr.+=:(60)

println(arr)

//添加一个集合所有元素
val arr7 = arr.++(Array(20,30,40))

println(arr7)

val arr8 = arr.++:(Array(20,30,40))
println(arr8)

arr.++=(Array(20,30,40))
println(arr)

arr.++=:(Array(60,70,80))
println(arr)

println("-----------------------")
println(arr)
arr.insert(2,100,200,300)
println(arr)

//删除元素
val arr9 = arr.-(60)
println(arr9)
println(arr)

arr.-=(60)
println(arr)

val arr10 = arr.--(Array(10,20,30,4,5,6,7))
println(arr10)

arr.--=(Array(60,70,80))
println(arr)

arr.remove(2,3)
println(arr)

//更新角标数据: 数组名(角标) = 值
arr(0)=1000
println(arr)

//获取角标数据: 数组名(角标)
println(arr(0))

//可变数组转不可变数组
val arr11 = arr.toArray
println(arr11)

//多维数组
val arr12 = Array.ofDim[Int](2,3)
println(arr12.length)
println(arr12(0).length)

数组转换

arr1.toBuffer //不可长数组转可变数组

arr2.toArray //可变数组转不可变数组

  1. arr2.toArray返回结果才是一个不可变数组,arr2本身没有变化
  2. arr1.toBuffer返回结果才是一个可变数组,arr1本身没有变化

seq集合(List)

不可变List

创建方法

  1. 通过apply方法创建: List[ 元素类型 ] ( 初始元素,....)
  2. 通过 :: 方法创建: 初始元素 :: 初始元素 :: ... :: Nil/不可变List 或者 list.::(初始元素)
    • :: 最右边必须是Nil或者是不可变List
    • Nil其实可以当做一个空的不可变List, Nil一般用作给不可变List变量赋予初始值,Nil与不可变List的关系类似Null与String
    • Nil给不可变List变量赋予初始值的时候,变量类型必须指定。

添加元素方法:

:: 是添加单个元素[类似之前不带=的一个+的方法]
::: 是添加一个集合所有元素[类似之前不带=的两个的方法]

代码演示

//通过apply方法创建: List[元素类型](初始元素,....)
val list1 = List[Int](10,2,5,4,3)

//通过 :: 方法创建:
val list2 = 2 :: 3 :: 4 :: 5 :: Nil

println(list1)
println(list2)
println(Nil)

//var list3 = Nil

//list3 = list2

//添加元素
val list3 = list2.+:(10)
println(list3)

val list4 = list2.:+(20)
println(list4)

val list5 = list2.::(30)
println(list5)

val list6 = list2.++(List(100,33,22))
println(list6)

val list7 = list2.++:(Array(44,55,66))
println(list7)
//扁平化处理
val list8 = list2.:::(List(66,77,88))
println(list8)

//获取角标元素
println(list8(0))

//修改指定角标元素
val list9 = list8.updated(0,666)
println(list8)
println(list9)

//不可变List转可变
println(list9.toBuffer)

可变List创建

  1. 通过apply方法: ListBuffer[元素类型](初始元素,..
  2. 通过new方式: new ListBuffer[元素类型] ()

代码演示

//通过apply方法: ListBuffer[元素类型](初始元素,....)
val list1 = ListBuffer[Int](10,3,2,6,7)

val list2 = new ListBuffer[Int]()

println(list1)
println(list2)

//添加元素
val list3 = list1.:+(20)
println(list3)

val list4 = list1.+:(30)
println(list4)

list1.+=(40)
println(list1)

list1.+=:(50)
println(list1)

list1.insert(2,60,70)
println(list1)

val list5 = list1.++(List(100,22,33))
println(list5)

val list6 = list1.++:(List(11,44,77))
println(list6)

list1.++=(List(444,555,666))
println(list1)

list1.++=:(List(777,888,999))
println(list1)

//删除
val list7 = list1.-(10)
println(list7)

list1.-=(999)
println(list1)

val list8 = list1.--(List(3,2,6,7,10))
println(list8)

list1.--=(List(3,2,6,7,10))
println(list1)

list1.remove(2,4)
println(list1)

//获取指定角标元素
println(list1(0))

//修改指定角标元素
list1(0)=100
println(list1)

//可变List转不可变List
println(list1.toList)

set集合

不可变set

不可变Set的创建: immutable.Set[元素类型] (初始元素,....)

set的特性:无序,不重复

代码演示

//不可变Set的创建: immutable.Set[元素类型](初始元素,....)
val set = Set[Int](10,10,2,4,7,6,2)

println(set)


//添加元素
val set2 = set.+(50)
println(set2)

val set3 = set.++(List(100,300,200,33))
println(set3)

val set4 = set.++:(List(100,300,200,33))
println(set4)

//删除元素
val set5 = set.-(2)

println(set5)

val list6 = set.--(List(7,4))
println(list6)

可变set

可变Set创建: mutable.Set[元素类型] (初始元素,....)

代码演示

val set = mutable.Set[Int](10,3,2,6,7)

println(set)

//添加元素
val set2 = set.+(20)

set.+=(30)

println(set2)
println(set)

val set3 = set.++(List(33,11,55,44))
val set4 = set.++:(List(33,11,55,44))
println(set3)
println(set4)

set.++=(List(77,888,33))
println(set)

set.add(100)
println(set)

//删除元素
val set6 = set.-(2)
println(set6)

set.-=(3)
println(set)

val set7 = set.--(List(6,7,77))
println(set7)
val set8 = set.--=(List(33,30,2))
println(set8)
println(set)
println(set.eq(set8))

set.remove(888)
println(set)

set.update(6,false)
println(set)

元组

元组的创建:

  • 通过()创建: (初始元素,....)
  • 通过->方式[只适用于创建二元元组]: K -> V
  • scala中二元元组表示KV键值对

元组的注意点

  1. 元组最多只能存放22个元素

  2. 元组一旦定义,元素和长度都不可以改变

  3. 元组获取元素: 元组名._N [N是元素的角标,元组的角标从1开始]

代码演示

class Region(name:String,school:School)

class School(name:String,clazz:Clazz)

class  Clazz(name:String, stu:Student)

class Student(name:String,age:Int)

Main:
	//1、通过()创建:  (初始元素,....)
    val t1 = ("lisi",20,"shenzhen")

    //2、通过->方式[只适用于创建二元元组]: K -> V
    val t2 = "zhangsan" -> 100

    println(t1)
    println(t2)

    println(t1._3)

    val lines = Source.fromFile("datas/log.txt").getLines()

    val logs = for(line<- lines) yield{
      val arr = line.split("\t")

      ( arr(0) , arr(1), arr(2).toInt , arr(3) )
    }


    val list = List(
      new Region("宝安区",new School("宝安中学",new Clazz("法师班",new Student("安其拉",20)))),
      new Region("宝安区",new School("宝安中学",new Clazz("法师班",new Student("王昭君",18)))),
      new Region("宝安区",new School("宝安中学",new Clazz("法师班",new Student("甄姬",16)))),
      new Region("宝安区",new School("宝安中学",new Clazz("法师班",new Student("小乔",22))))
    )

    val list2 = List(
      ("宝安区",("宝安中学",("法师班",("安其拉",20)))),
      ("宝安区",("宝安中学",("法师班",("王昭君",20)))),
      ("宝安区",("宝安中学",("法师班",("甄姬",20)))),
      ("宝安区",("宝安中学",("法师班",("小乔",20))))
    )

    for( element<- list2 ) {
      println( element._2._2._2._1  )
    }

Map集合

不可变map

不可变Map创建

immutable.Map[K的类型,V的类型] ( (K,V), K->V,... )

需要注意的地方

  • Option: 为了提醒外部当前结果有可能为空,需要自己处理
  • Some: 代表不为空,结果封装在Some中,后续可以调用get方法获取结果
  • None: 代表为空

map获取元素

​ getOrElse(key,默认值): 如果map中key存在则返回key对应的value值,如果key不存在则返回默认值

代码演示

val map = Map[String,Int]("aa"->10, ("bb",20),"ac"->30,"dc"->40,"cc"->60)

println(map)

//添加元素
val map2 = map.+( "cd"->100 )
println(map2)

val map3 = map.++( List( "ee"->70 ,"ff"->80) )
println(map3)

val map4 = map.++:(List( "gg"->200,"oo"->300))
println(map4)

//删除元素
val map5 = map.-("ac")
println(map5)

val map6 = map.--(List("cc","dc"))
println(map6)

//获取元素
//根据key获取value值
//println(map("ac1"))
//val option = map.get("ac1")
//if(!option.isEmpty){
//  println(option.get)
//}
println(map.getOrElse("ac1", -1))

//获取所有的key
for( key<- map.keySet) println(key)

//获取所有的value值
for(value<- map.values) println(value)

//修改元素
val map11 = map.+( "aa"->100 )
println(map11)

val map12 = map.updated("aa",1000)
println(map12)

可变map

可变Map的创建: mutable.Map[K的类型,V的类型] ( K->V , (K,V),... )

代码演示

val map = mutable.Map[String,Int]("aa"->10,"cd"->20,"ad"->40)
println(map)

//添加元素
val map2 = map.+( "ee"->50 )
println(map2)

map.+=( "ff"->60 )
println(map)

val map3 = map.++(List("tt"->20,"pp"->30))

println(map3)
map.++=(List("oo"->30,"gg"->40))
println(map)

map.put("rr",100)
println(map)
//删除
val map5 = map.-("oo")
println(map5)

map.-=("gg")
println(map)

val map6 = map.--(List("rr","cd"))
println(map6)

map.--=(List("aa","cd","ad"))
println(map)

map.remove("oo")
println(map)

//获取元素
//根据key获取value值
println(map.getOrElse("ff", -1))

//获取所有的key
println(map.keys)
//获取value
println(map.values)

//修改value值
map("rr1")=2000
println(map)

map.put("gg",500)
println(map)

常用函数

基本属性和常用操作

  1. 获取集合长度
  2. 获取集合大小
  3. 循环遍历
  4. 迭代器
  5. 生成字符串
  6. 是否包含

代码演示

	val list: List[Int] = List(1, 2, 3, 4, 5, 6, 7)

    //(1)获取集合长度
    println(list.length)

    //(2)获取集合大小
    println(list.size)

    //(3)循环遍历
    list.foreach(println)

    //(4)迭代器
    for (elem <- list.iterator) {
    println(elem)
    }

    //(5)生成字符串
    println(list.mkString(","))

    //(6)是否包含
    println(list.contains(3))

衍生集合

  1. 获取集合的头head
  2. 获取集合的尾(不是头就是尾)tail
  3. 集合最后一个数据 last
  4. 集合初始数据(不包含最后一个)
  5. 反转
  6. 取前(后)n个元素
  7. 去掉前(后)n个元素
  8. 并集
  9. 交集
  10. 差集
  11. 拉链
  12. 滑窗

代码演示

    val list1: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
    val list2: List[Int] = List(4, 5, 6, 7, 8, 9, 10)

    //(1)获取集合的头
    println(list1.head)

    //(2)获取集合的尾(不是头的就是尾)
    println(list1.tail)

    //(3)集合最后一个数据
    println(list1.last)

    //(4)集合初始数据(不包含最后一个)
    println(list1.init)

    //(5)反转
    println(list1.reverse)

    //(6)取前(后)n个元素
    println(list1.take(3))
    println(list1.takeRight(3))

    //(7)去掉前(后)n个元素
    println(list1.drop(3))
    println(list1.dropRight(3))

    //(8)并集
    println(list1.union(list2))

    //(9)交集
    println(list1.intersect(list2))

    //(10)差集
    println(list1.diff(list2))

    //(11)拉链 注:如果两个集合的元素个数不相等,那么会将同等数量的数据进行拉链,多余的数据省略不用
    println(list1.zip(list2))

    //(12)滑窗
    list1.sliding(2, 5).foreach(println)

集合计算初级函数

  1. 求和
  2. 求乘积
  3. 最大值
  4. 最小值
  5. 排序

代码演示

	val list: List[Int] = List(1, 5, -3, 4, 2, -7, 6)

    //(1)求和
    println(list.sum)

    //(2)求乘积
    println(list.product)

    //(3)最大值
    println(list.max)

    //(4)最小值
    println(list.min)

    //(5)排序
    // (5.1)按照元素大小排序
    println(list.sortBy(x => x))

    // (5.2)按照元素的绝对值大小排序
    println(list.sortBy(x => x.abs))

    // (5.3)按元素大小升序排序
	println(list.sortWith((x, y) => x < y))

	// (5.4)按元素大小降序排序
    println(list.sortWith((x, y) => x > y))

集合计算高级函数

  1. 过滤
  2. 转化/映射
  3. 扁平化
  4. 扁平化+映射 注:flatMap相当于先进行map操作,在进行flatten操作
  5. 分组
  6. 简化(规约)
  7. 折叠

代码演示

	val list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
    val nestedList: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9))
    val wordList: List[String] = List("hello world", "hello atguigu", "hello scala")

    //(1)过滤
    println(list.filter(x => x % 2 == 0))

    //(2)转化/映射
    println(list.map(x => x + 1))

    //(3)扁平化
    println(nestedList.flatten)

    //(4)扁平化+映射 注:flatMap相当于先进行map操作,在进行flatten操作
    println(wordList.flatMap(x => x.split(" ")))

    //(5)分组
    println(list.groupBy(x => x % 2))
	
	// (6) reduce
	// 将数据两两结合,实现运算规则
        val i: Int = list.reduce( (x,y) => x-y )
        println("i = " + i)

        // 从源码的角度,reduce底层调用的其实就是reduceLeft
        //val i1 = list.reduceLeft((x,y) => x-y)

        // ((4-3)-2-1) = -2
        val i2 = list.reduceRight((x,y) => x-y)
        println(i2)

		// (7) fold方法使用了函数柯里化,存在两个参数列表
        // 第一个参数列表为 : 零值(初始值)
        // 第二个参数列表为:

        // fold底层其实为foldLeft
        val i = list.foldLeft(1)((x,y)=>x-y)

        val i1 = list.foldRight(10)((x,y)=>x-y)

        println(i)
        println(i1)

队列

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

并行集合

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

		//单核
		val result1 = (0 to 100).map{case _ => Thread.currentThread.getName}
		//多核
        val result2 = (0 to 100).par.map{case _ => Thread.currentThread.getName}
        println(result1)
        println(result2)

posted @ 2021-10-29 18:25  KaneQi  阅读(28)  评论(0编辑  收藏  举报