Scala中的Queue&Map&Set&集合操作用法

1 队列 Queue

  • 队列数据存取符合先进先出策略

1.1 队列的创建

    import scala.collection.mutable
    val q1 = new mutable.Queue[Int]
    println(q1)
Queue()

1.2 队列元素的追加

    q1 += 1
    println(q1)
Queue(1)

1.3 向队列中追加 List

    q1 ++= List(2, 3, 4) //追加集合中的元素
    println(q1)
Queue(1, 2, 3, 4)

1.4 按照进入队列的顺序删除元素

    q1.dequeue()
    println(q1)
Queue(2, 3, 4)

1.5 塞入数据

    q1.enqueue(9, 8, 7)
    println(q1)
Queue(2, 3, 4, 9, 8, 7)

1.6 返回队列的第一个元素

println(q1.head)
2

1.7 返回队列最后一个元素

println(q1.last)
7

1.8 返回除了第一个以外剩余的元素(尾部)

println(q1.tail.tail.head)  //可以用于递归调用
4

2 映射 Map

2.1 构造不可变映射

val map1 = Map[String,Int]("Alice" -> 10, "Bob" -> 20, "Kotlin" -> 30)

2.2 构造可变映射

val map2 = scala.collection.mutable.Map("Alice" -> 10, "Bob" -> 20, "Kotlin" -> 30)    

2.3 空的映射

val map3 = new scala.collection.mutable.HashMap[String, Int]

2.4 对偶元组(包含键值对的二元组)

val map4 = Map(("Alice", 10), ("Bob", 20), ("Kotlin", 30))

2.5 取值

val value1 = map1("Alice")
    println(value1)
  • 如果映射中没有值,则会抛出异常,使用 contains 方法检查是否存在 key。 (不推荐使用)
 println(map1("a"))
Exception in thread "main" java.util.NoSuchElementException: key not found: a
	at scala.collection.MapLike$class.default(MapLike.scala:228)
	at scala.collection.AbstractMap.default(Map.scala:59)
	at scala.collection.MapLike$class.apply(MapLike.scala:141)
	at scala.collection.AbstractMap.apply(Map.scala:59)
	at com.nefu.scala.chaptor06.Scala05_Map$.main(Scala05_Map.scala:22)
	at com.nefu.scala.chaptor06.Scala05_Map.main(Scala05_Map.scala)

  • 如果通过 映射.get(键) 这样的调用返回一个 Option 对象,要么是 Some,要么是 None。(避免异常)
    //Option -> Some,None
    println(map1.get("Alice"))
    println(map1.get("a"))
Some(10)
None
  • 默认值方法: getOrElse
    println(map1.getOrElse("Bob",100))
    //如果a键位没有获取到数据,默认值就是100
    println(map1.getOrElse("a",100))
20
100

2.6 遍历 map

    /*
    遍历 map
     */
    //得到所有Key
    for(k <- map.keys){
      println(k + "-------------->" + map.get(k))
    }
    //得到所有value
    for(v <- map.values){
      println("value:" + v)
    }
    //得到k-v对
    for((k,v) <- map){
      println(k+"="+v)
    }

    for(item <- map){
      println(item._1 + "====" + item._2)
    }
A-------------->Some(1)
B-------------->Some(2)
value:1
value:2
A=1
B=2
A====1
B====2

2.6 更新值

    map += "D" -> 4 //并不是改变了集合 而是新建了一个新的对象
    map -= "B"

3 集 Set

  • 集是不重复元素的结合。集不保留顺序,默认是以哈希集实现。
  • 如果想要按照已排序的顺序来访问集中的元素,可以使用 SortedSet(已排序数据集),已排序的数据集是用红黑树实现的。 极限情况下放 11 个元素变成树
  • 默认情况下, Scala 使用的是不可变集合,如果你想使用可变集合,需要引用
    scala.collection.mutable.Set 包

3.1 Set 不可变集合的创建

val set = Set(1, 2, 3)

3.2 Set 可变集合的创建,如果 import 了可变集合,那么后续使用默认也是可变集合

import scala.collection.mutable.Set
    val mutableSet = Set(1, 2, 3)

3.3 可变集合的元素添加

    mutableSet.add(4)
    mutableSet += 6

3.4 注意该方法返回一个新的 Set 集合,而非在原有的基础上进行添加

mutableSet.+(5)

3.5 可变集合的元素删除

   mutableSet -= 1
    mutableSet.remove(2)

3.6 遍历

    for(x <- mutableSet) {
      println(x)
    }

4 集合元素的映射&筛选

4.1 map

  • 将集合中的每一个元素通过指定功能(函数)映射(转换)成新的结果集合这里其实就是所谓的将函数作为参数传递给另外一个函数,这是函数式编程的特点
  def main(args: Array[String]): Unit = {
    val arr1s = 1 to 5

    def plus2(i:Int):Int={
      i * 2
    }
    //函数作为参数的用法是Scala的精华
    val arr2s = arr1s.map(plus2)
    for(v <- arr2s){
      println(v)
    }
  }
2
4
6
8
10

4.2 flatMap

  • flat 即压扁,压平,扁平化,效果就是将集合中的每个元素的子元素映射到某个函数并返回新的集合
    val list = List("Tom","Jerry")

    def strToUpper(s:String): String ={
      s.toUpperCase()
    }
    //Hadoop的MapReduce中的Mapper!
    val list1 = list.map(strToUpper)
    println(list1)

    //压扁 扁平化转换(集合中不会再有集合的转换处理方式)
    val list2 = list.flatMap(strToUpper)
    println(list2)
List(TOM, JERRY)
List(T, O, M, J, E, R, R, Y)

4.3 filter

  • 将符合要求的数据(筛选)放置到新的集合中
    val arr1s = List("Tom","Jerry","Bob","Jack","tim")

    //数据的筛选处理
    def strFilter(s:String):Boolean={
      s.toUpperCase.startsWith("T") || s.toLowerCase.startsWith("j")
    }
    val arr2s = arr1s.filter(strFilter)
    println(arr2s)

    val arr3s= arr1s.filterNot(strFilter)
    println(arr3s)
List(Tom, Jerry, Jack, tim)
List(Bob)

5 化简、折叠、扫描

5.1 折叠,化简

  • 将二元函数引用于集合中的函数
    val list = List(1,2,3,4,5)

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

    def list2Str(i:Int,s:Any):Any={
     "" + s + i
    }

    def listMinus(x:Int,y:Int):Int={
      
      x - y
    }
    //从左侧开始加
    val result1 = list.reduceLeft(listAdd)
    println(result1)
    //从右侧开始加
    val result2 = list.reduceRight(list2Str)
    println(result2)

    val result3 = list.reduceRight(listMinus)
    println(result3)
    /*
      4 - 5 = -1
      3 - (-1) = 4
      2 - 4 = -2
      1 - (-2) = 3
       */
15
54321
3

5.2 折叠,化简:fold

  • fold 函数将上一步返回的值作为函数的第一个参数继续传递参与运算,直到 list 中的所有元素被遍历。 可以把 reduceLeft 看做简化版的 foldLeft。相关函数: foldfoldLeftfoldRight,可以参考 reduce 的相关方法理解。
val list = List(1,2,3,4,5)

    def listAdd(r:Int,p:Int):Int={
      r + p
    }

    def listMinus(p:Int,r:Int):Int={
      r - p
    }

    //1 +
    //100 + 1 = 101 + 2 = 103 + 3 = 106 ...
    val result1 = list.foldLeft(100)(listAdd)
    println(result1)

    val result2 = list.foldRight(100)(listMinus)
    println(result2)

    var arr = new mutable.ArrayBuffer[Any]
    arr += "hello"
    val lst = List(10,20,30,40,50)

    def addEle(ab:mutable.ArrayBuffer[Any],ele:Int):mutable.ArrayBuffer[Any]={
      ab += ele
    }
    val result = lst.foldLeft(arr)(addEle)
    println(result)
115
85
ArrayBuffer(hello, 10, 20, 30, 40, 50)

5.3 折叠,化简, 扫描

  • 这个理解需要结合上面的知识点,扫描,即对某个集合的所有元素做 fold 操作,但是会把产生的所有中间结果放置于一个集合中保存。
    def listAdd(r:Int,p:Int):Int={
      r + p
    }
    //1 +
    //100 + 1 = 101 + 2 = 103 + 3 = 106 ...
    val result1 = list.foldLeft(100)(listAdd)
    //扫描的每一个折叠小单元的结果
    val result2 = list.scanLeft(100)(listAdd)
    println(result1)
    println(result2)
115
List(100, 101, 103, 106, 110, 115)

6 拉链

  • 集合的合并操作
    //1.  拉链
    val list1 = List(1,2,3)
    val list2 = List(4,5,6,7)

    val result = list1 zip list2

    val result1 = list1 zip result
    println(result1)
List((1,(1,4)), (2,(2,5)), (3,(3,6)))
List((1,4), (2,5), (3,6))

7 迭代器

  • 你可以通过 iterator 方法从集合获得一个迭代器,通过 while 循环和 for 表达式对集合进行遍历。
val iterator = List(1, 2, 3, 4, 5).iterator
while (iterator.hasNext) {
println(iterator.next())
}
或:
for(enum <- iterator) {
println(enum)
}

8 流 Stream

  • stream 是一个集合。这个集合,可以用于存放,无穷多个元素, 但是这无穷个元素并不会一次性生产出来,而是需要用到多大的区间,就会动态的生产,末尾元素遵循 lazy规则

8.1 使用#::得到一个 stream

    def numsForm(n: BigInt) : Stream[BigInt] ={
      n #:: numsForm(n + 1) //懒加载
    }

8.2 传递一个值,并打印 stream 集合

val tenOrMore = numsForm(1)
    println(tenOrMore)
Stream(1, ?)

8.3 tail 的每一次使用,都会动态的向 stream 集合按照规则生成新的元素

    println(tenOrMore.tail)
    println(tenOrMore)
Stream(2, ?)
Stream(1, 2, ?)
  • 1 stream 不能使用 last 属性 ,会出现死循环

8.4 使用 map 映射 stream 的元素并进行一些计算

def multi(x:Int) : Int {
      x * x
    }
    println(numsForm(5).map(multi))
  }

9 视图

  • Stream 的懒加载特性,也可以对其他集合应用 view 方法来得到类似的效果,该方法产出一个其方法总是被懒执行的集合。但是 view 不会缓存数据,每次都要重新计算。
  • 例如: 我们找到 100 以内,所有数字倒序排列还是它本身的数字。

10 线程安全的集合

  • 所有线程安全的集合都是以 Synchronized 开头的集合,例如:
SynchronizedBuffer
SynchronizedMap
SynchronizedPriorityQueue
SynchronizedQueue
SynchronizedSet
SynchronizedStack

11 并行集合

  • Scala 为了充分使用多核 CPU,提供了并行集合(有别于前面的串行集合),用于多核环境的并行计算。
  • 主要用到的算法有:
  1. Divide and conquer : 分治算法, Scala 通过 splitters, combiners 等抽象层来实现,主要原理是将计算工作分解很多任务,分发给一些处理器去完成, 并将它们处理结果合并返回
  2. Work stealin: 算法, 主要用于任务调度负载均衡(load-balancing),通俗点完成自己的所有任务之后,发现其他人还有活没干完,主动(或被安排)帮他人一起干,这样达到尽早干完的目的。

11.1 打印 1-5

    (1 to 5).foreach(println)
    println()
    (1 to 5).par.foreach(println)
1
2
3
4
5

4
3
5
2
1

11.2 查看并行集合中元素访问的线程

    val result3 = (0 to 100).map{case _ => Thread.currentThread.getName}.distinct// (去重)
    val result4 = (0 to 100).par.map{case _ => Thread.currentThread.getName}.distinct
    println(result3)
    println(result4)
Vector(main)
ParVector(ForkJoinPool-1-worker-7, ForkJoinPool-1-worker-1, ForkJoinPool-1-worker-5, ForkJoinPool-1-worker-3)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值