Scala 基础语法
友情推荐
参考
Scala 参考文档 (scala-lang.org)
[Scala 教程 ](
Scala 是运行在 JVM 上的多范式编程语言,同时支持面向对象和面向函数编程
① Scala 可以更加高效的开发 kafaka、Spark、Flink 等大数据应用程序
② Scala 的表能能力比 Java 更强
③ 兼容 Java ,能使用很多 Java 的类库,如:mysql、redis、freemarker、activemq 等
启动、退出
# 启动 Scala 解释器
scala
# 退出解释器
:quit
# 查看帮助
:help
数据类型与运算符
数据类型
① Scala 中所有的类型都使用大写字母开头
② Scala 中定义变量可以不写类型,让 Scala 编译器自动推断
基础类型 | 类型说明 |
---|---|
Byte | 8位带符号整数 |
Short | 16位带符号整数 |
Int | 32位带符号整数 |
Long | 64位带符号整数 |
Char | 16位无符号Unicode字符 |
String | Char类型的序列(字符串) |
Float | 32位单精度浮点数 |
Double | 64位双精度浮点数 |
Boolean | true或false |
运算符
① Scala 中没有,++
、--
运算符
② 在 Scala 中,可以直接使用 ==
、!=
进行比较,它们与 equals
方法表示一致,而比较两个对象的引用值,使用 eq
类别 | 操作符 |
---|---|
算术运算符 | +、-、*、/ % |
关系运算符 | >、<、==、!=、>=、<= |
逻辑运算符 | &&、||、! |
位运算符 | &、||、^、<<、>> |
数据类型层次结构
类型 | 说明 |
---|---|
Any | 所有类型的父类,它有两个子类AnyRef与AnyVal |
AnyVal | 所有数值类型的父类 |
AnyRef | 所有对象类型(引用类型)的父类 |
Unit | 表示空,Unit是AnyVal的子类,它只有一个的实例() 它类似于Java中的void,但scala要比Java更加面向对象 |
Null | Null是AnyRef的子类,也就是说它是所有引用类型的子类。它的实例是null 。可以将null赋值给任何对象类型 |
Nothing | 所有类型的子类 不能直接创建该类型实例,某个方法抛出异常时,返回的就是Nothing类型,因为Nothing是所有类的子类,那么它可以赋值为任何类型。我们程序员不使用Nothing,这个是系统自行维护的。。 |
声明变量
语法格式
注意:Scala 的语句最后不需要添加分号
# 格式
val/var 变量标识:变量类型 = 初始值
# 示例
val name:String = "Kyle"
val 和 var 变量的区别
① val
定义的是不可重新赋值的变量(优先使用)
② var
定义的是可重新赋值的变量
通过类型推断定义变量
Scala 可以自动根据变量的值来自动推断变量的类型,代码会更加简洁
# 格式
val/var 变量标识 = 初始值
# 示例
val name = "Kyle"
惰性赋值
当有一些变量保存的数据较大时,但是不需要马上加载到 JVM 内存,可以使用惰性赋值来提高效率
# 格式
# 必须为 val 变量
lazy val 变量标识 = 初始值
字符串
字符串的定义方式
① 使用双引号
# 格式
val/var 变量名 = “字符串”
# 示例
val name = "Kyle"
② 使用插值表达式
# 格式
val/var 变量名 = s"${变量/表达式}字符串"
# 示例:name 和 age 都是上文定义的变量
val desc = s"name=${name}, age=${age}"
③ 使用三引号
# 格式:用于大段的文本
val/var 变量名 = """字符串1
字符串2"""
# 示例:
val sql = """
select
*
from
user
"""
条件表达式
说明
条件表达式就是 if
表达式,if
表达式可以根据给定的条件是否满足,根据条件的结果(真或假)决定执行对应的操作
有返回值的 if
① 在 Scala 中,条件表达式也是有返回值的
② 在 Scala 中,没有三元表达式,可以使用 if
表达式替代三元表达式
# 示例
val temp = 2
if(temp == 2) {1} else {0}
块表达式
① Scala 中,使用 {}
表示一个块表达式
② 和 if
表达式一样,块表达式也是有值的,值就是最后一行代码表达式的值
# 示例
val a = {
println(" hello world ")
2 / 2
}
循环
说明
在 Scala 中,可以使用 for
和 while
,但一般推荐使用 for
表达式,因为 for
表达式语法更简洁
for 循环
// 格式
for(i <- 表达式/数组/集合) {
// 表达式
}
// 示例:第一种写法
val nums = 1.to(10)
nums: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
for(i <- nums) println(i)
// 示例:第二种写法
for(i <- 1 to 10) println(i)
for 表达式:守卫
for
表达式中,可以添加if判断语句,这个 if
判断就称之为守卫
// 格式
for(i <- 表达式/数组/集合 if 表达式) {
// 表达式
}
// 示例:打印能够整除 3 的数字
for(i <- 1 to 10 if i % 3 == 0) println(i)
for 推导式
使用 for
推导式生成一个新的集合(一组数据)
// 生成一个 1 - 10 的集合
// for推导式:for表达式中以yield开始,该for表达式会构建出一个集合
val v = for(i <- 1 to 10) yield i
while 循环
// 打印1-10的数字
while(i <= 10) {
pirintln(i)
i = i + 1
}
break 和 continue
① 在 Scala 中,类似 Java
和 C++
的 break/continue
关键字被移除了
② 使用 scala.util.control
包的 Breaks
类的 breakable
和 break
方法进行替代 break/continue
// 实现 break:使用 for 表达式打印 1-10 的数字,如果数字到达 5,退出 for 表达式
// 导入scala.util.control包下的Break
import scala.util.control.Breaks._
breakable{
for(i <- 1 to 100) {
if(i >= 50) break()
else println(i)
}
}
// 实现 continue:打印 1-10 的数字,使用 for 表达式来遍历,如果数字能整除 3,不打印
// 导入scala.util.control包下的Break
import scala.util.control.Breaks._
for(i <- 1 to 10 ) {
breakable{
if(i % 3 == 0) break()
else println(i)
}
}
方法
定义方法
① 参数列表的参数类型不能省略
② 返回值类型可以省略,由 Scala 编译器自动推断
③ 返回值可以不写 return
,默认就是 {}
块表达式的值
def methodName (参数名:参数类型, 参数名:参数类型) : [return type] = {
// 方法体:一系列的代码
}
调用方法
// 定义方法
def add(a:Int, b:Int) = a + b
// 调用方法
add(2,2)
方法参数
① 默认参数
// 定义方法:参数有默认值
def add(x:Int = 0, y:Int = 0) = x + y
// 调用方法
add()
② 带名参数
// 定义方法
def add(x:Int = 0, y:Int = 0) = x + y
// 调用方法时,指定方法的参数
add(x=1)
③ 变长参数
// 定义方法
// 在参数类型后面加一个*号,表示参数可以是0个或者多个
def add(num:Int*) = num.sum
// 调用方法
add(1,2,3,4,5)
方法的调用方式
① 后缀调用法
// 格式
对象名.方法名(参数)
// 示例:求绝对值
Math.abs(-1)
② 中缀调用法
// 格式
对象名 方法名 参数
// 示例:求绝对值
Math abs -1
③ 花括号调用法
注意:方法只有一个参数,才能使用花括号调用法
// 格式
Math.abs{
// 表达式1
// 表达式2
}
// 示例
Math.abs{-10}
④ 无括号调用法
注意:如果方法没有参数,可以省略方法名后面的括号
def method()=println("hello")
⑤ 操作符即方法
在 Scala
中,+ - * / %
等这些操作符和 Java
一样,但在 Scala
中,所有的操作符都是方法;操作符是一个方法名字,是符号的方法
// 示例
2 * 3
函数
定义函数
① 函数是一个对象(变量)
② 类似于方法,函数也有输入参数和返回值
③ 函数定义不需要使用 def
定义
④ 无需指定返回值类型
// 格式
val 函数变量名 = (参数名:参数类型, 参数名:参数类型....) => {函数体}
// 示例:定义一个两数相加的函数
val add = (x:Int, y:Int) => x + y
方法和函数的区别
① 方法是隶属于类或者对象的 ( 对象包含方法 ),在运行时,它是加载到 JVM
的方法区中
② 可以将函数对象赋值给一个变量,在运行时,它是加载到 JVM
的堆内存中
③ 函数是一个对象,继承自FunctionN,函数对象有 apply,curried,toString,tupled 这些方法。方法则没有
方法转换为函数
某些情况下,需要将方法转换为函数,作为变量传递,就需要将方法转换为函数,使用 _
即可将方法转换为函数
// 定义方法
def add(x:Int,y:Int) = x+y
// 转换为函数,此时的变量 a 为函数对象
val a = add _
数组
数组的分类
① 定长数组
定长数组指的是数组的长度是不允许改变的,数组内的元素可以改变
② 不定长数组
不定长数组指的是数组的长度是可以改变,数组内的元素可以改变
定长数组的定义
// 第一种定义:通过指定长度定义数组
val/var 变量名 = new Array[元素类型](数组长度)
// 示例:定义一个长度为 10 的 Int 类型的数组
val array1 = new Array[Int](10)
// 第二种定义:用元素直接初始化数组
val/var 变量名 = Array(元素1, 元素2, 元素3...)
// 示例:定义一个包含元素 从 0 到 9 的数组,长度为元素的个数
val array2 = Array(0,1,2,3,4,5,6,7,8,9)
变长数组的定义
// 第一种定义:创建空的变长数组
val/var a = ArrayBuffer[元素类型]()
// 示例:创建空的变长数组,类型为 Int
import scala.collection.mutable.ArrayBuffer
val array_buffer1 = ArrayBuffer[Int]()
// 第二种定义:创建包含初始元素的变长数组
val/var a = ArrayBuffer(元素1,元素2,元素3....)
// 示例
import scala.collection.mutable.ArrayBuffer
val array_buffer2 = ArrayBuffer(0,1,2,3,4,5,6,7,8,9)
变长数组:添加/修改/删除元素
val array = ArrayBuffer("a", "b", "c")
① 使用 +=
添加元素
array += "d"
② 使用 -=
删除元素
array -= "d"
③ 使用 ++=
追加一个数组到变长数组
array ++= Array("x","y","z")
数组遍历
① 使用 for
表达式直接遍历数组中的元素
val array2 = Array(0,1,2,3,4,5,6,7,8,9)
// 遍历
for(i <- array2) println(i)
② 使用 索引
遍历数组中的元素
val array2 = Array(0,1,2,3,4,5,6,7,8,9)
// 遍历
for(i <- 0 to array2.length - 1) println( a(i) )
for(i <- 0 until array2.length) println( a(i) )
数组常用的算法
val array2 = Array(0,1,2,3,4,5,6,7,8,9)
// 获取指定下标的元素
array2(1)
// 求和
array2.sum
// 求最大值
array2.max
// 求最小值
array2.min
// 升序排序
array2.sorted
// 反转
array2.reverse
// 降序
array2.sorted.reverse
元组
元组可以用来包含一组不同类型的值
定义元组
// 格式:使用括号来定义元组
val/var 元组 = (元素1, 元素2, 元素3....)
// 格式:使用箭头来定义元组(只支持元组只有两个元素时)
val/var 元组 = 元素1->元素2
// 添加一条学生的信息
val stu1 = (1, "Kyle", 23, "Haikou")
// 添加一条学生的信息
val stu2 = "Lisa" -> 24
访问元组
val stu1 = (1, "Kyle", 23, "Haikou")
// 访问第一个元素
stu1._1
// ...
stu1._2
stu1._3
...
列表(有序可重复)
① 不可变列表(不可变集合都在 immutable
包中,默认导入)
② 可变列表(可变集合都在 mutable
包中)
注意:Scala 在遍历 Java 的 java.util.List
时,需要使用隐式转换
import scala.collection.JavaConversions._
不可变列表(长度、元素不可变)
// 第一种:创建一个 不可变列表
val/var 变量名 = List(元素1, 元素2, 元素3...)
// 第二种:创建一个 不可变空列表
val/var 变量名 = Nil
// 第三种:使用 :: 创建一个不可变列表
// 注意:必须在最后添加一个 Nil
val/var 变量名 = 元素1 :: 元素2 :: Nil
可变列表(长度、元素可变)
// 创建一个空的可变列表
import scala.collection.mutable.ListBuffer
val/var 变量名 = ListBuffer[T]()
// 示例:创建一个整数类型的空列表
val mutable_list1 = ListBuffer[Int]()
// 创建一个有初始元素的可变列表
import scala.collection.mutable.ListBuffer
val/var 变量名 = ListBuffer(元素1,元素2,元素3...)
// 示例:创建一个整数类型的列表
val mutable_list2 = ListBuffer(1, 2, 3)
可变列表的常用操作
import scala.collection.mutable.ListBuffer
val mutable_list3 = ListBuffer("abc", "xy", "Kyle",101)
// 获取第一个元素(使用括号访问(索引值)
mutable_list3(0)
// 添加一个元素(+=)
mutable_list3 += 4
// 追加一个列表(++=)
mutable_list3 ++= List(5,6,7)
// 更改元素(使用括号获取元素,然后进行赋值)
mutable_list3(3) = 10
// 删除元素(-=)
mutable_list3 -= 10
// 转换为List(toList)
mutable_list3.toList
// 转换为Array(toArray)
mutable_list3.toArray
列表的常用操作
val list = List("Kyle","Jack","Lisa")
// 判断列表是否为空(isEmpty)
list.isEmpty
// 拼接两个列表(++)
list ++ List("Sam","Rose")
// 反转列表(reverse)
list.reverse
// 获取前缀(take):获取前 2 个元素
list.take(2)
// 扁平化(flatten)
scala> val a = List(List(1,2), List(3), List(4,5))
a: List[List[Int]] = List(List(1, 2), List(3), List(4, 5))
scala> a.flatten
res0: List[Int] = List(1, 2, 3, 4, 5)
// 转换字符串(toString)
list.toString
// 生成字符串(mkString),可以指定元素之间的分隔符
list.mkString(",")
Set(无序不可重复)
① 可变集
② 不可变集(添加、删除、更新操作都会返回一个新的集合)
不可变集
// 创建空的不可变集
val/var 变量名 = Set[类型]()
// 创建一个有元素的不可变集
val/var 变量名 = Set(元素1, 元素2, 元素3...)
不可变集的操作
val set1 = Set(1,2,3,4,5)
// 获取集的大小(size)
set1.size
// 遍历集(和遍历数组一致)
for(i <- set1) println(i)
// 添加一个元素,生成一个Set(+)
set1 + 6
// 删除一个元素
set1 - 1
// 拼接两个集,生成一个Set(++)
set1 ++ Set(7,8,9)
// 拼接集和列表,生成一个Set(++)
a ++ List(10,11)
可变集
注意:可变集和不可变集的创建方式一致,但是需要提前导入一个可变集类
import scala.collection.mutable.Set
val mutable_set = Set(1,2,3,4,5)
// 增加元素 +=
mutable_set += 6
// 减少元素
mutable_set -= 6
映射(Map)
① 可变 Map
② 不可变 Map
不可变 Map
// 格式
// 推荐,可读性更好
val/var map = Map(键->值, 键->值, 键->值...)
val/var map = Map((键, 值), (键, 值), (键, 值), (键, 值)...)
// 示例
var map1 = Map("Kyle"->23, "Lisa"->25, "Jack"->26)
可变 Map
定义可变 Map
需要手动导入 import scala.collection.mutable.Map
// 格式
import scala.collection.mutable.Map
val/var map = Map(键->值, 键->值, 键->值...)
Map 基本操作
var map1 = Map("Kyle"->23, "Lisa"->25, "Jack"->26)
// 获取值(map(key))
map1("Kyle")
// 获取所有key(map.keys)
map1.keys
// 获取所有value(map.values)
map1.values
// 遍历map集合
for((x,y) <- map1) println(s"$x $y")
// getOrElse:如果 Kris 不在,就返回 -1
map1.getOrElse("Kris", -1)
// 增加key,value对
map1 + "Kris"->35
// 删除key
map1 - "Jack"
iterator 迭代器
Scala 针对每一类集合都提供了一个迭代器(iterator)用来迭代访问集合
① hasNext——查询容器中是否有下一个元素
② next——返回迭代器的下一个元素,如果没有,抛出 NoSuchElementException
val list = List(1,2,3,4,5)
val iterator = list.iterator
while(iterator.hasNext) {println(iterator.next)}
异常处理
捕获异常
① try 中的代码是我们编写的业务处理代码
② 在 catch 中表示当出现某个异常时,需要执行的代码
③ 在 finally 中,是不管是否出现异常都会执行的代码
// 语法格式
try {
// 代码
}
catch {
case ex:异常类型1 => // 代码
case ex:异常类型2 => // 代码
}
finally {
// 代码
}
try {
val i = 10 / 0
} catch {
case ex: Exception => println(ex.getMessage)
}
抛出异常
注:Scala 中的异常抛出不需要在方法上声明
def main(args: Array[String]): Unit = {
throw new Exception("这是一个异常")
}
函数式编程
遍历 | foreach
// 格式
集合对象.foreach(f: (A) ⇒ Unit): Unit
foreach | API | 说明 |
---|---|---|
参数 | f: (A) ⇒ Unit | 接收一个函数对象 函数的输入参数为集合的元素,返回值为空 |
返回值 | Unit | 空 |
// 定义一个列表
val list = List(1,2,3,4)
// 迭代打印
list.foreach((x:Int)=>println(x))
使用类型推断简化函数定义
Scala可以自动来推断出来集合中每个元素参数的类型
// 由于每个元素的类型是确定的,使用类型推断简化函数定义
list.foreach(x=>println(x))
使用下划线来简化函数定义
当函数参数,只在函数体中出现一次,而且函数体没有嵌套调用时,可以使用下划线来简化函数定义
list.foreach(println(_))
映射 | map
map方法接收一个函数,将这个函数应用到每一个元素,返回一个新的集合
// 格式
def map[B](f: (A) ⇒ B): TraversableOnce[B]
map方法 | API | 说明 |
---|---|---|
泛型 | [B] | 指定map方法最终返回的集合泛型 |
参数 | f: (A) ⇒ B | 传入一个函数对象 该函数接收一个类型A(要转换的列表元素),返回值为类型B |
返回值 | TraversableOnce[B] | B类型的集合 |
val list = List(1,2,3,4)
// 对 List 中的每一个元素加 1
list.map(x=>x+1)
val list = List(1,2,3,4)
// 对 List 中的每一个元素加 1,使用下划线来定义函数
list.map(_ + 1)
val list = List("Hello","Jack","Lisa","Kyle")
list.map((_,1))
扁平化映射 | flatMap
使用频率高,可以把 flatMap,理解为先 map,然后再 flatten
① map 是将列表中的元素转换为一个 List
② flatten 再将整个列表进行扁平化
def flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): TraversableOnce[B]
flatmap方法 | API | 说明 |
---|---|---|
泛型 | [B] | 最终要转换的集合元素类型 |
参数 | f: (A) ⇒ GenTraversableOnce[B] | 传入一个函数对象 函数的参数是集合的元素 函数的返回值是一个集合 |
返回值 | TraversableOnce[B] | B类型的集合 |
// 需求:将 List 中的全部元素按照空格分隔,最终将所有的结果放在一个集合里
// 定义文本行列表
val a = List("aa bb cc dd ee", "11 22 33 44")
// 使用 map 将文本行转换为单词数组
a.map(x=>x.split(" "))
// 扁平化,将数组中的元素放在一个 List 中
a.map(x=>x.split(" ")).flatten
// 使用 flatMap 简化操作
a.flatMap(_.split(" "))
过滤 | filter
// 格式
def filter(p: (A) ⇒ Boolean): TraversableOnce[A]
filter方法 | API | 说明 |
---|---|---|
参数 | p: (A) ⇒ Boolean | 传入一个函数对象 接收一个集合类型的参数 返回布尔类型,满足条件返回true, 不满足返回false |
返回值 | TraversableOnce[A] | 列表 |
// 过滤出所有的偶数
List(1,2,3,4,5,6,7,8,9).filter(_ % 2 == 0)
排序|sorted sortBy sortWith
① sorted 默认排序
② sortBy 指定字段排序
③ sortWith 自定义排序
默认排序(sorted)
// 对列表升序排序
List(3,1,2,9,7).sorted
指定字段排序(sortBy)
根据传入的函数转换后,再进行排序
// 格式
def sortBy[B](f: (A) ⇒ B): List[A]
sortBy方法 | API | 说明 |
---|---|---|
泛型 | [B] | 按照什么类型来进行排序 |
参数 | f: (A) ⇒ B | 传入函数对象 接收一个集合类型的元素参数 返回B类型的元素进行排序 |
返回值 | List[A] | 返回排序后的列表 |
// 按照元素的开头进行排序
val a = List("02 Jack", "01 Lisa", "04 Sam", "03 Kris" )
// 排序
a.sortBy(_.split(" ")(1))
自定义排序(sortWith)
自定义排序,根据一个函数来进行自定义排序
def sortWith(lt: (A, A) ⇒ Boolean): List[A]
sortWith方法 | API | 说明 |
---|---|---|
参数 | lt: (A, A) ⇒ Boolean | 传入一个比较大小的函数对象 接收两个集合类型的元素参数 返回两个元素大小,小于返回true,大于返回false cj:对原列表的当前元素x,跟其他元素(比如用y表示)比较。(x,y)如果经过函数处理后,返回true,那么编译器认为x小,x排结果列表在前面,y往后排。 |
返回值 | List[A] | 返回排序后的列表 |
// 定义一个列表
val a = List(2,3,1,6,4,5)
// 对列表的元素进行排序
a.sortWith((x,y) => if(x<y)true else false)
val a = List(2,3,1,6,4,5)
// 定义一个排序函数
val b=(x:Int,y:Int)=> if(x>y) true else false
a.sortWith(b)
a.sortWith((x:Int,y:Int)=> if(x>y) true else false)
a.sortWith((x,y)=> if(x>y) true else false)
// 函数参数只在函数中出现一次,可以使用下划线代替
a.sortWith(_ > _)
分组|groupBy
groupBy 表示按照函数将列表分成不同的组
// 格式
def groupBy[K](f: (A) ⇒ K): Map[K, List[A]]
groupBy方法 | API | 说明 |
---|---|---|
泛型 | [K] | 分组字段的类型 |
参数 | f: (A) ⇒ K | 传入一个函数对象 接收集合元素类型的参数 返回一个K类型的key,这个key会用来进行分组,相同的key放在一组中 |
返回值 | Map[K, List[A]] | 返回一个映射,K为分组字段,List为这个分组字段对应的一组数据 |
val a = List("Kyle"->"男", "Lisa"->"女", "Jack"->"男", "Kris"->"男")
// 按照性别分组
a.groupBy(_._2)
// 将分组后的映射转换为性别/人数元组列表
res0.map(x => x._1 -> x._2.size)
聚合|reduce
reduce 表示将列表,传入一个函数进行聚合计算
注:reduce 和 reduceLeft 效果一致,表示从左到右计算,reduceRight 表示从右到左计算
// 格式
def reduce[A1 >: A](op: (A1, A1) ⇒ A1): A1
reduce方法 | API | 说明 |
---|---|---|
泛型 | [A1 >: A] | (下界)A1必须是集合元素类型的父类 |
参数 | op: (A1, A1) ⇒ A1 | 传入函数对象,用来不断进行聚合操作 第一个A1类型参数为:上次聚合后的临时变量 第二个A1类型参数为:当前要进行聚合的元素 |
返回值 | A1 | 列表最终聚合为一个元素 |
val a = List(1,2,3,4,5,6,7,8,9,10)
// 第 1 种:将集合的所有元素相加
a.reduce((x,y) => x + y)
// 第 2 种:简写
// 第一个下划线表示第一个参数,就是历史的聚合数据结果
// 第二个下划线表示第二个参数,就是当前要聚合的数据元素
a.reduce(_ + _)
// 第 3 种:与reduce一样,从左往右计算
a.reduceLeft(_ + _)
// 第 4 种:从右往左聚合计算
a.reduceRight(_ + _)
折叠 | fold
fold 与 reduce 很像,但是多了一个指定初始值参数
注:fold 和 foldLet 效果一致,表示从左往右计算,foldRight 表示从右往左计算
// 格式
def fold[A1 >: A](z: A1)(op: (A1, A1) ⇒ A1): A1
reduce方法 | API | 说明 |
---|---|---|
泛型 | [A1 >: A] | (下界)A1必须是集合元素类型的父类 |
参数1 | z: A1 | 初始值 |
参数2 | op: (A1, A1) ⇒ A1 | 传入函数对象,用来不断进行折叠操作 第一个A1类型参数为:当前折叠后的变量 第二个A1类型参数为:当前要进行折叠的元素 |
返回值 | A1 | 列表最终折叠为一个元素 |
val a = List(1,2,3,4,5,6,7,8,9,10)
// 初始值为0,在初始值的基础上,将集合的所有元素相加
a.fold(0)(_ + _)