Scala入门系列(十):函数式编程之集合操作

1. Scala的集合体系结构

Scala中的集合体系主要包括(结构跟Java相似):

  • Iterable(所有集合trait的根trait)
  • Seq(Range、ArrayBuffer、List等)
  • Set(HashSet、LinkedHashSet、SortedSet等)
  • Map (HashMap、SortedMap、LinkedHashMap等)

Scala中的集合分为可变和不可变两类集合,分别对应scala.collection.mutable和scala.collection.immutable两个包。

2. List

List代表一个不可变的列表。

  • List有head和tail,head代表List的第一个元素,tail代表第一个元素之后的所有元素。
scala> val list = List(1, 2, 3, 4) 
list: List[Int] = List(1, 2, 3, 4) 
 
scala> list.head 
res33: Int = 1 
 
scala> list.tail 
res34: List[Int] = List(2, 3, 4) 

  
案例:用递归函数给List中每个元素都加上指定的前缀并打印

// 如果List只有一个元素,那么他的tail就是Nil 
def decorator(list: List[Int], prefix: String){ 
  if (list != Nil) { 
    println(prefix + list.head) 
    decorator(list.tail, prefix) 
  } 
} 
 
scala> decorator(list, "+") 
+1 
+2 
+3 
+4 

  • List有特殊的::操作符,可以用于将head和tail合并成一个List。
scala> list 
res37: List[Int] = List(1, 2, 3, 4) 
 
scala> 0::list 
res38: List[Int] = List(0, 1, 2, 3, 4) 

该操作符在Spark源码中有体现

3. LinkedList

LinkedList代表一个可变的列表,其elem和next属性类似于List的head和tail。

案例:使用while循环将LinkedList中每个一个元素乘以二。

val list = scala.collection.mutable.LinkedList(1,2,3,4,5,6,7,8,9) 
var currentList = list 
var first = true 
while( currentList !=Nil && currentList.next != Nil){ 
  if(first) { currentList.elem *= 2; first = false} 
  currentList = currentList.next.next 
  if(currentList != Nil) currentList.elem *= 2 
} 
 
list: scala.collection.mutable.LinkedList[Int] = LinkedList(2, 2, 6, 4, 10, 6, 14, 8, 18) 

4. Set

Set代表一个没有重复元素的集合

HashSet

不保证插入顺序,元素是乱序的

scala> val s = new scala.collection.mutable.HashSet[Int]() 
s: scala.collection.mutable.HashSet[Int] = Set() 
 
scala> s += 1 
res40: s.type = Set(1) 
 
scala> s += 2 
res41: s.type = Set(1, 2) 
 
scala> s += 5 
res42: s.type = Set(1, 5, 2) 

LinkedHashSet

保证插入顺序,底层使用链表

scala> val s = new scala.collection.mutable.LinkedHashSet[Int]() 
s: scala.collection.mutable.LinkedHashSet[Int] = Set() 
 
scala> s += 1 
res43: s.type = Set(1) 
 
scala> s += 2 
res44: s.type = Set(1, 2) 
 
scala> s += 5 
res45: s.type = Set(1, 2, 5) 

SortedSet

会自动根据key来进行排序(默认字母顺序)

scala> val s = scala.collection.mutable.SortedSet("orange", "apple", "banana") 
s: scala.collection.mutable.SortedSet[String] = TreeSet(apple, banana, orange) 

5. 集合的函数式编程(重要!)

Scala中集合的函数式编程最大的体现就是对于一系列高阶函数的使用。

高阶函数的使用是Scala与Java最大的区别!因为Java中没有函数式编程,也肯定没有高阶函数,无法直接将函数传入一个方法,或者让一个方法返回一个函数。

// 为List中的每个元素都添加一个前缀 
scala> List("leo", "spark","peter").map("name is " + _) 
res47: List[String] = List(name is leo, name is spark, name is peter) 
 
// 拆分单词 
scala> List("Hello world", "your are my friend").flatMap(_.split(" ")) 
res48: List[String] = List(Hello, world, your, are, my, friend) 
 
// 打印每一个元素 
scala> List("Hello world", "your are my friend").foreach(println(_)) 
Hello world 
your are my friend 
 
// 学生姓名和成绩进行关联 
scala> List("leo", "jen", "jack").zip(List(100, 30, 20)) 
res50: List[(String, Int)] = List((leo,100), (jen,30), (jack,20)) 

6. 综合案例:统计多个文本内的单词总数

// 使用scala的IO包将文件文件内的数据读取出来 
scala> val lines1 = scala.io.Source.fromFile("E://test.txt").mkString 
lines1: String = hello my 
 
scala> val lines2 = scala.io.Source.fromFile("E://test2.txt").mkString 
lines2: String = you are a good boy 
 
// 使用List的伴生对象,将多个文件内的内容创建为一个List 
scala> val lines = List(lines1, lines2) 
lines: List[String] = List(hello my, you are a good boy) 
// 首先将所有元素以空格分割单词,接着将每个单词映射为(单词,1)元组, 然后再取出元组里的第二个元素(_._2表示取出元组中的第二个元素),最后做累加 
scala> lines.flatMap(_.split(" ")).map((_, 1)).map(_._2).reduceLeft(_ + _) 
res51: Int = 7 

注意:最后一行多个高阶函数的链式调用其实就是Scala函数式编程的精髓所在,也是Scala相较于Java等编程语言最大的功能优势所在。并且Spark的源码中大量使用了这种复杂的链式调用,Spark本身提供的开发API也完全沿用了Scala的函数式编程。

posted @   小丑进场  阅读(616)  评论(0编辑  收藏  举报
编辑推荐:
· 为什么构造函数需要尽可能的简单
· 探秘 MySQL 索引底层原理,解锁数据库优化的关键密码(下)
· 大模型 Token 究竟是啥:图解大模型Token
· 35岁程序员的中年求职记:四次碰壁后的深度反思
· 继承的思维:从思维模式到架构设计的深度解析
阅读排行:
· 【保姆级教程】windows 安装 docker 全流程
· 基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程
· 由 MCP 官方推出的 C# SDK,使 .NET 应用程序、服务和库能够快速实现与 MCP 客户端
· 电商平台中订单未支付过期如何实现自动关单?
· X86-64位简易系统开发 - 从BIOS阶段开始
点击右上角即可分享
微信分享提示