11 Scala 数据结构(下)-集合操作

数据结构(下)-集合操作

1. 集合元素的映射:map 映射操作

1.1 map 映射操作

  1. 通过 map 映射操作可以解决:将集合中的每一个元素通过指定功能映射成新的结果集合,这里其实就是所谓的将函数作为参数传递给另外一个函数,这是函数式编程的特点。

  2. HashSet 为例说明:

    def map[B](f:(A) => B): HashSet[B]  // map函数的签名
    

    2.1 [B] 是泛型。
    2.2 map 是一个高阶函数(可以接受一个函数的函数,就是高阶函数),可以接受函数 f:(A)=>B
    2.3 HashSet[B] 就是返回的新的集合。

1.2 案例

  1. 要求:请将 List(3,5,7) 中的所有元素都 * 2 ,将其结果放到一个新的集合中返回,即返回一个新的 List(6,10,14), 请编写程序实现。

    val list = List(2,5,7)
    
    def multiple(n:Int): Int = {
      2 * n
    }
    
    val newList = list.map(multiple)
    
    println(newList)   // List(6,10,14)
    

1.3 flatmap 映射

  1. flatmapflat 即压扁,压平,扁平化,效果就是将集合中的每个元素的子元素映射到某个函数并返回新的集合。

  2. 案例:

    //需求是将 List 集合中的所有元素,进行扁平化操作,即把所有元素打散
    val names = List("zgl", "zzx", "zzz")
    
    def upper(s: String): String = {
      s.toUpperCase
    }
    
    val newNames = names.flatMap(upper)
    print(newNames)  // List(Z, G, L, Z, Z, X, Z, Z, Z)
    

2. 集合元素的过滤:filter

  1. filter :将符合要求的数据放置到新的集合中。

  2. 案例

    // 将 List("Alice", "Bob", "Nick") 集合中首字母为'A'的筛选到新的集合。
    val names = List("Alice", "Bob", "Nick")
    
    def startA(name: String): Boolean = {
          name.startsWith("A")
    }
    
    val newNames = names.filter(startA)
    print(newNames)   // List("Alice")
    

3. 化简

  1. reduceleft(f) 的运行规则是:从左边开始执行将得到的结果返回给第一个参数,然后继续和下一个元素运行,将得到的结果继续返回给第一个参数,继续。

  2. reduceright(f)

  3. reduce(f):同 reduceleft(f)

  4. 案例:

    // val list = List(1, 20, 30, 4 ,5) , 求出 list 的和
    val list = List(1, 20, 30, 4, 5)
    
    def sum(n1: Int, n2: Int): Int = {
      n1 + n2
    }
    
    list.reduceLeft(sum)   // (((1+20) +30) +4) +5 = 60
    list.reduceRight(sum)  // 1+ (20+ (30+ (4+5))) = 60
    list.reduce(sum)       // (((1+20) +30) +4) +5 = 60
    

4. 折叠

  1. fold 函数将上一步返回的值作为函数的第一个参数继续传递参与运算,直到 list 中的所有元素被遍历。

  2. 可以把 reduceLeft 看做简化版的 foldLeft

  3. 相关函数:fold,foldLeft,foldRight,可以参考 reduce 的相关方法理解。

  4. 案例:

    val list = List(1, 2, 3, 4)
    
    def minus( num1 : Int, num2 : Int ): Int = {
      num1 - num2
    }
    
    list.foldLeft(5)(minus)   // (((5-1) -2) -3) -4 = -5
    list.foldRight(5)(minus)  // 1- (2- (3- (4-5))) = 3
    list.fold(5)(minus)       // (((5-1) -2) -3) -4 = -5
    
  5. foldLeftfoldRight 缩写方法分别是:/::\

    var res1 = (5 /: list)(minus)  // list.foldLeft(5)(minus) 
    var res2 = (list :\ 5)(minus)  // list.foldRight(5)(minus)
    

5. 扫描

  1. 扫描,即对某个集合的所有元素做 fold 操作,但是会把产生的所有中间结果放置于一个集合中保存。

  2. 案例:

    def minus( num1 : Int, num2 : Int ): Int = {
      num1 - num2
    }
    val res1 = (1 to 5).scanLeft(5)(minus)  // (5, 4, 2, -1, -5, -10)
    
    def add( num1 : Int, num2 : Int ) : Int = { 
      num1 + num2 
    }
    val res2 = (1 to 5).scanRight(5)(add)   // (20, 19, 17, 14, 10, 5)
    

6. 拉链

  1. 当我们需要将两个集合进行对偶元组合并,可以使用拉链。

  2. 案例:

    val list1 = List(1, 2, 3) 
    val list2 = List(4, 5, 6) 
    
    val list3 = list1.zip(list2) // (1,4),(2,5),(3,6) 
    
  3. 拉链的本质就是两个集合的合并操作,合并后每个元素是一个对偶元组。

  4. 如果两个集合个数不对应,会造成数据丢失。

  5. 集合不限于 List , 也可以是其它集合比如 Array

  6. 如果要取出合并后的各个对偶元组的数据,可以通过遍历。

7. 迭代器

  1. 通过 iterator 方法从集合获得一个迭代器,通过 while 循环和 for 表达式对集合进行遍历。

  2. 案例:

    val iterator = List(1, 2, 3, 4, 5).iterator // 得到迭代器
    
    // while 形式
    while (iterator.hasNext) { 
      println(iterator.next()) 
    }
    
    // for 形式
    for(enum <- iterator) { 
      println(enum) 
    }
    

8. 流 Stream

8.1 基本说明

  1. stream 是一个集合。这个集合,可以用于存放无穷多个元素,但是这无穷个元素并不会一次性生产出来,而是需要用到多大的区间,就会动态的生产,末尾元素遵循 lazy 规则(即:要使用结果才进行计算的) 。

8.2 创建 Stream 对象

def numsForm(n: BigInt) : Stream[BigInt] = n #:: numsForm(n + 1) 
val stream1 = numsForm(1)
  • Stream 集合存放的数据类型是 BigInt
  • numsForm 是自定义的一个函数,函数名是程序员指定的。
  • 创建的集合的第一个元素是 n , 后续元素生成的规则是 n + 1
  • 后续元素生成的规则是可以程序员指定的 ,比如 numsForm( n * 4)

8.3 案例

//创建 Stream 
def numsForm(n: BigInt) : Stream[BigInt] = n #:: numsForm(n + 1) 

val stream1 = numsForm(1) 
println(stream1) 
println("head=" + stream1.head) //取出第一个元素 
println(stream1.tail) // 当对流执行 tail 操作时,就会生成一个新的数据.

9. 视图 View

9.1 基本介绍

  1. Stream 的懒加载特性,也可以对其他集合应用 view 方法来得到类似的效果,具有如下特点:
    1.1 view 方法产出一个总是被懒执行的集合。
    1.2 view 不会缓存数据,每次都要重新计算,比如遍历 View 时。

9.2 案例

// 请找到 1-100 中,数字倒序排列和它本身相同的所有数。

//如果这个数,逆序后和原来数相等,就返回 true,否则返回 false 
def eq(i: Int): Boolean = { 
  i.toString.equals(i.toString.reverse) 
}

//说明: 没有使用 view,常规方式 
val viewSquares1 = (1 to 100).filter(eq)

//使用 view ,是在使用到结果才执行,则可以使用 view 来进行优化. 
val viewSquares2 = (1 to 100).view.filter(eq)
//遍历 
for (item <- viewSquares2) { 
  println("item=" + item) 
}

10. 并行集合

  1. Scala 为了充分使用多核 CPU,提供了并行集合(有别于前面的串行集合),用于多核环境的并行计算。
  2. 使用:(1 to 5).par.foreach(println(_))

11. 操作符

  1. 如果想在变量名、类名等定义中使用语法关键字(保留字),可以配合反引号。

    val `val` = 5
    
  2. 中置操作符:A 操作符 B 等同于 A.操作符(B)

  3. 后置操作符:A 操作符 等同于 A.操作符,如果操作符定义的时候不带 () 则调用时不能加括号。

  4. 前置操作符,+、-、!、~操作符 A 等同于 A.unary_操作符

  5. 赋值操作符,A 操作符= B 等同于 A = A 操作符 B

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值