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

本文深入解析Scala中的集合操作,包括flatmap、filter、reduce、fold、scan、zip、iterator、stream、view、parallel collection及操作符等。通过具体示例阐述各函数的使用场景和执行流程,帮助读者掌握Scala集合高效编程技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.flatmap

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

object Scala02_FlatMapDemo01 {
  def main(args: Array[String]): Unit = {
    // 将List集合中的所有元素,进行扁平化操作,即把所有元素打散
    val names = List("Alice", "Bob", "Nick")
    val names2 = names.flatMap(upper)
    println("names2=" + names2)
  }
  def upper( s : String ) : String = {
    s. toUpperCase
  }
}

2.filter

  集合元素的过滤

object Scala03_FilterDemo01 {
  def main(args: Array[String]): Unit = {
    // 选出首字母为A的元素
    val names = List("Alice", "Bob", "Nick")
    val names2 = names.filter(startA)
    println("names=" + names)
    println("names2=" + names2)
  }
  def startA(str:String): Boolean = {
    str.startsWith("A")
  }
}

3.化简

    将二元函数引用于集合中的函数。

object Scala04_ReduceDemo01 {
  def main(args: Array[String]): Unit = {
    // 使用化简的方式来计算list集合的和
    val list = List(1, 20, 30, 4, 5)
    val res = list.reduceLeft(sum) //接收一个函数时,也可以直接传入一个匿名函数
    //执行的流程分析
    //步骤 1 (1 + 20)
    //步骤 2 (1 + 20) + 30
    //步骤 3 ((1 + 20) + 30) + 4
    //步骤 4 (((1 + 20) + 30) + 4) + 5 = 60
    println("res="+res) // 60
  }
  def sum(n1: Int, n2: Int): Int = {
    println("sum被调用~~")
    n1 + n2
  }
}

4.折叠

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

object Scala05_FoldDemo01 {
  def main(args: Array[String]): Unit = {

    val list = List(1, 2, 3, 4)
    def minus( num1 : Int, num2 : Int ): Int = {
      num1 - num2
    }

    //说明
    //1. 折叠的理解和化简的运行机制几乎一样.
    //理解 list.foldLeft(5)(minus) 理解成 list(5,1, 2, 3, 4) list.reduceLeft(minus)
    //步骤  (5-1)
    //步骤  ((5-1) - 2)
    //步骤  (((5-1) - 2) - 3)
    //步骤  ((((5-1) - 2) - 3)) - 4 = - 5
    println(list.foldLeft(5)(minus)) // 函数的柯里化

    // 理解 list.foldRight(5)(minus) 理解成 list(1, 2, 3, 4, 5) list.reduceRight(minus)
    // 步骤 (4 - 5)
    // 步骤 (3- (4 - 5))
    // 步骤 (2 -(3- (4 - 5)))
    // 步骤 1- (2 -(3- (4 - 5))) = 3
    println(list.foldRight(5)(minus)) //函数的柯里化

  }
}

4.1 折叠缩写:foldLeft 和 foldRight 缩写方法分别是: /: 和 :\

object Scala05_FoldDemo02 {
  def main(args: Array[String]): Unit = {

    val list4 = List(1, 9)
    def minus(num1: Int, num2: Int): Int = {
      num1 - num2
    }
    var i6 = (1 /: list4) (minus) // =等价=> list4.foldLeft(1)(minus)
    println("i6=" + i6)

    i6 = (100 /: list4) (minus) //=等价=> list4.foldLeft(100)(minus)
    println(i6)

    i6 = (list4 :\ 10) (minus) // list4.foldRight(10)(minus)
    println(i6)

  }
}

5.扫描

object Scala06_ScanDemo01 {
  def main(args: Array[String]): Unit = {

    //普通函数:左扫描
    def minus( num1 : Int, num2 : Int ) : Int = {
      num1 - num2
    }
    //5 (1,2,3,4,5) =>(5, 4, 2, -1, -5, -10)
    val i8 = (1 to 5).scanLeft(5)(minus)
    println("i8=" + i8)

    //普通函数:右扫描
    def add( num1 : Int, num2 : Int ) : Int = {
      num1 + num2
    }
    //(1,2,3,4,5) 5 => (20,19,17,14, 10,5)
    val i9 = (1 to 5).scanRight(5)(add)
    println("i9=" + i9)

  }
}

6. 拉链

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

/**
 * 拉链使用注意事项:
 * 1) 拉链的本质就是两个集合的合并操作,合并后每个元素是一个 对偶元组。
 * 2) 如果两个集合个数不对应,会造成数据丢失。
 * 3) 集合不限于 List, 也可以是其它集合比如 Array。
 * 4) 如果要取出合并后的各个对偶元组的数据,可以遍历。
 */
object Scala07_ZipDemo01 {
  def main(args: Array[String]): Unit = {
    // 拉链
    val list1 = List(1, 2, 3)
    val list2 = List(4, 5, 6)
    val list3 = list1.zip(list2) // (1,4),(2,5),(3,6)
    println("list3=" + list3)
  }
}

7.迭代器

object Scala08_IteratorDemo01 {
  def main(args: Array[String]): Unit = {
    val iterator = List(1, 2, 3, 4, 5).iterator // 得到迭代器

    println(" === 遍历方式1 while === ")
    while (iterator.hasNext) {
      println(iterator.next())
    }

    println(" === 遍历方式2 for === ")
    for(enum <- iterator) {
      println(enum)
    }
  }
}

8.流

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

/**
 * 流:stream 是一个集合。这个集合,可以用于存放无穷多个元素,但这无穷个元素并不会一次性生产出来,而是需要用到多大的区间,就会动态的生产,末尾元素遵循 lazy 规则 。
 * 说明
 * 1) Stream 集合存放的数据类型是 BigInt
 * 2) numsForm 是自定义的一个函数,函数名是程序员指定的。
 * 3) 创建的集合的第一个元素是 n , 后续元素生成的规则是 n + 1
 * 4) 后续元素生成的规则是可以程序员指定的 ,比如 numsForm( n * 4)...
 */
object Scala09_StreamDemo01 {
  def main(args: Array[String]): Unit = {

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

    //取出第一个元素
    println("head=" + stream1.head) // 1
    println(stream1.tail) // 2
    println(stream1) //? (1,2,...)

    // 看一个应用案例
    def multi(x:BigInt) : BigInt = {
      x * x
    }
    println(numsForm(5).map(multi))

  }
}

9.视图

/**
 * 视图:
 * Stream 的懒加载特性,也可以对其他集合应用 view 方法来得到类似的效果,具有如下特点:
 * 1) view方法产出一个总是被懒执行的集合。
 * 2) view不会缓存数据,每次都要重新计算,比如遍历View时。
 *
 * 练习:请找到 1-100 中,数字倒序排列 和它本身相同的所有数。(1 2, 11, 22, 33 ...)
 */
object Scala10_ViewDemo01 {
  def main(args: Array[String]): Unit = {

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

    //说明: 没有使用view
    val viewSquares1 = (1 to 100).filter(eq)
    println(viewSquares1)

    //说明:使用view,来完成这个问题,程序中对集合进行map,filter,reduce,fold...
    // 当你并不希望立即执行,而是在使用到结果才执行,则可以使用view来进行优化.
    val viewSquares2 = (1 to 100).view.filter(eq)
    println(viewSquares2)
    //遍历
    for (item <- viewSquares2) {
      println("item=" + item)
    }

  }
}

10.并行集合

object Scala11_ParallelCollection {
  def main(args: Array[String]): Unit = {

    // 打印1~5
    (1 to 5).foreach(println(_))
    println()
    (1 to 5).par.foreach(println(_))

    // 查看并行集合中元素访问的线程
    val result1 = (0 to 10000).map{case _ => Thread.currentThread.getName}.distinct
    val result2 = (0 to 10000).par.map{case _ => Thread.currentThread.getName}.distinct
    println(result1)
    println(result2)

  }
}

11.操作符

/**
 * 操作符:
 * 1) 如果想在变量名、类名等定义中使用语法关键字(保留字),可以配合反引号反引号 val `val` = 42
 * 2) 中置操作符:A 操作符 B 等同于 A.操作符(B)
 * 3) 后置操作符:A 操作符 等同于 A.操作符,如果操作符定义的时候不带()则调用时不能加括号。
 * 4) 前置操作符,+、-、!、~等操作符 A 等同于 A.unary_操作符
 * 5) 赋值操作符,A操作符=B等同于A=A操作符B ,比如A+=B等价A=A+B
 */
object Scala12_OperatorDemo01 {
  def main(args: Array[String]): Unit = {

    val n1 = 1
    val n2 = 2
    val r1 = n1 + n2 // 3
    val r2 = n1.+(n2) // 3

    val monster = new Monster
    monster + 10
    monster.+(10)

    println("monster.money=" + monster.money) // 20

    println(monster++)
    println(monster.++)

    println("monster.money=" + monster.money) // 22

    !monster
    println("monster.money=" + monster.money) // -22
  }
}

class Monster {
  var money: Int = 0

  //对操作符进行重载 (中置操作符)
  def +(n:Int): Unit = {
    this.money += n
  }
  //对操作符进行重载(后置操作符)
  def ++(): Unit = {
    this.money += 1
  }

  //对操作符进行重载(前置操作符,一元运算符)
  def unary_!(): Unit = {
    this.money = -this.money
  }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员学习圈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值