栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 其他

Scala笔记(一)基本简介与基础语法

其他 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Scala笔记(一)基本简介与基础语法

文章目录
  • 一、Scala 简介
    • 1.1 什么是 Scala
    • 1.2 为什么使用 Scala
  • 二、Scala 环境搭建
    • 2.1 程序编译执行流程
    • 2.2 安装 Scala SDK
    • 2.3 安装 IDEA scala 插件
  • 三、Scala 基础语法
    • 3.1 变量与常量
    • 3.2 字符串
    • 3.3 数据类型与操作符
      • 数据类型
      • 操作符
      • Scala 类型层次结构
  • 四、流程控制
    • 4.1 条件表达式
      • if 表达式
      • 块表达式
    • 4.2 循环
      • for 表达式
      • while 循环
      • break 和 continue
  • 五、方法和函数
    • 5.1 方法
      • 方法定义
      • 方法参数
      • 方法调用方式
    • 5.2 函数
      • 定义函数
      • 方法和函数的区别
      • 方法转换为函数
      • 偏函数
  • 六、集合
    • 6.1 数组
      • 定长数组
      • 变长数组
      • 遍历数组
      • 数组的常用算法
    • 6.2 元组
      • 定义元组
      • 访问元组
    • 6.3 列表
      • 不可变列表
      • 可变列表
      • 列表常用操作
    • 6.4 集合
      • 不可变集
      • 可变集
    • 6.5 映射
    • 6.6 Option 类型
    • 6.7 iterator 迭代器
  • 七、函数式编程
    • 7.1 遍历(foreach)
    • 7.2 映射(map)
    • 7.3 映射扁平化(flatmap)
    • 7.4 过滤(filter)
    • 7.5 是否存在(exists)
    • 7.6 排序(sorted、sortBy、sortWith)
    • 7.7 分组(groupBy)
    • 7.8 聚合计算(reduce)
    • 7.9 折叠(fold)

一、Scala 简介 1.1 什么是 Scala

Scala 是运行在 JVM 上的多范式编程语言,同时支持面向对象和面向函数编程。

  • 面向对象特性:
    • 所有变量都是对象
    • 对象的数据类型和行为由类和特征描述
    • 利用特征实现混入式多重继承
  • 函数式编程:
    • 每个函数都是一个值
    • 支持高阶函数
1.2 为什么使用 Scala
  • 开发大数据应用程序(Spark 程序、Flink 程序)
  • 表达能力强,一行代码抵得上 Java 多行,开发速度快
  • 兼容 Java,可以访问庞大的 Java 类库
二、Scala 环境搭建 2.1 程序编译执行流程
  • Java 程序编译执行流程
  • Scala 程序编译执行流程

    所以,要编译运行 scala 程序,需要
  • jdk(jvm)
  • scala 编译器(scala SDK)
2.2 安装 Scala SDK
  • Windows
    步骤:
    1. 从scala 官网中下载安装包
    2. 安装在指定目录,例如:d:/tools
    3. 配置环境变量:
      增加系统环境变量 SCALA_HOME=安装路径,
      修改系统环境变量path=%SCALA_HOME%bin;...
    4. 测试是否安装成功:打开控制台,输入scala -version
  • Linux
    步骤:
    1. 从scala 官网中下载安装包
    2. 上传到 linux 服务器指定目录下并解压
    3. 配置环境变量:
      执行vim /etc/profile编辑配置脚本
      增加环境变量export SCALA_HOME=安装路径
      在 Path 后追加 scala 的安装路径export PATH=$PATH:...:$SCALA_HOME/bin
    4. 测试是否安装成功:在 linux 终端输入scala -version
2.3 安装 IDEA scala 插件

IDEA 默认是不支持 scala 程序开发,所以需要安装 scala 插件来支持 scala 语言

  • 离线安装
    步骤:
    1. 到 IDEA 官网中下载与 IDEA 对应版本的IDEA scala 插件
    2. 在 IDEA 启动页面中,选择 Configure->Plugins
    3. 在弹出的页面中点击右上角的小齿轮,选择 Install Plugin from Disk 选择插件安装包
    4. 在 Installd 中显示了 scala 插件,表示安装成功
    5. 重启 IDEA
  • 在线安装
    1. 在 IDEA 菜单栏中选择 File->Settings->Plugins,进入到插件市场
    2. 搜索 scala,显示 scala 插件,点击 Install 进行安装
    3. 在 Installd 中显示了 scala 插件,表示安装成功
    4. 重启 IDEA
三、Scala 基础语法 3.1 变量与常量
  • 变量
var 变量名:类型 = 初始值 // 类型可不写,scala会自动根据变量的值来推断变量的类型
  • 常量(常用)
val 变量名:类型 = 初始值 // 类型可不写,scala会自动根据变量的值来推断变量的类型
  • 惰性赋值
    当有一些变量保存的数据较大时(比如 SQL 语句),不需要马上加载到 JVM 内存,可以使用惰性赋值来提高效率。
lazy val/var 变量名 =
      """
        |
        |select ...
        |from 表
        |
        |""".stripMargin
3.2 字符串

Scala 提供了多种定义字符串的方式

  • 使用双引号
val/var 变量名 = "字符串"
  • 使用插值表达式
// 适用于大量字符串的拼接
val/var 变量名 = s"$变量"
val/var 变量名 = s"${变量/表达式}"
  • 使用三引号
// 适用于保存大段的文本
val/var 变量名 = """
        |
        |select ...
        |from 表
        |
        |"""
3.3 数据类型与操作符 数据类型

Java 类型与Scala 的区别:
1. Scala 中所有的类型都使用大写字母开头
2. 整型使用 Int 而不是 Integer
3. Scala 中定义变量可以不写类型,Scala 编译器会自动推断

操作符
  • Scala 中没有 ++、-- 运算符,可以使用 +=、-= 进行运算
  • Scala 可以直接使用 ==、!=、equals 进行值的比较,而比较两个对象的引用值(即地址值),则使用 eq 方法
Scala 类型层次结构

类型说明
Any所有类型的父类,它有两个子类 AnyVal 与 AnyRef
AnyVal所有数值类型的父类
AnyRef所用对象类型(引用类型)的父类
Unit表示无值,Unit 是 AnyVal 的子类,它只有一个实例(),类似于 Java 中的 void
NullNull 是 AnyRef 的子类,它的实例是 null,可以将 null 赋值给任何对象类型
Nothing所有类型的子类,不能直接创建该类型实例,某个方法抛出异常时,返回的就是 Nothing 类型。因为 Nothing 是所有类的子类,那么它可以赋值为任何类型
四、流程控制 4.1 条件表达式 if 表达式
  • 在 Scala 中,条件表达式也是有返回值的
  • 在 Scala 中,没有三元表达式,可以使用 if 表达式替代三元表达式
val sex = "male"
val result = if(sex == "male") 1 else 0
println(result)  // 1
块表达式
  • 在 Scala 中,使用 {} 表示一个块表达式
  • 和 if 表达式一样,块表达式也是有值的
  • 值就是最后一个表达式的值
4.2 循环 for 表达式

语法:

for(i <- 表达式/数组/集合) {
	// 表达式
}
for(i <- 1 to 5) println(i) // 包含 5
for(i <- 1 until 5) println(i) // 不包含 5
  • 嵌套循环
for(i <- 1 to 3; j <- 1 to 5) {
	println("*")
	if(j == 5) println("")
}
  • 守卫
    在 for 表达式中添加 if 判断语句。
for(i <- 1 to 10 if i % == 0) println(i)
  • for 推导式
    在 for 循环体中,可以使用 yield 表达式构建出一个集合,我们把使用 yield 的 for 表达式称之为推导式。
val v = for(i <- 1 to 10) yield i * 10
while 循环

Scala 中的 while 循环跟 Java 是一致的。

while(i <= 10) {
	println(i)
	i = i + 1
}
break 和 continue

如果要在 Scala中使用 break/continue,就需要使用 scala.util.control 包的 Break 类的 breakble 和 break 方法。

  • 实现 break
    用法:
    • 导入 Breaks 包 import scala.util.control.Breaks._
    • 使用 breakable 将 for 表达式包起来
    • for 表达式中需要退出循环的地方,添加 break() 方法调用
// 导入scala.util.control包下的Break
import scala.util.control.Breaks._

// 不打印大于等于50的数
breakable{
	for(i <- 1 to 100) {
		if(i >= 50) break()
		println(i)
	}
}
  • 实现 continue
    用法:用 breakable{} 将 for 表达式的循环体包含起来。
// 导入scala.util.control包下的Break
import scala.util.control.Breaks._

// 不打印10的倍数
for(i <- 1 to 100) {
	breakable{
		if(i % 10 == 0) break()
		println(i)
	}
}
五、方法和函数 5.1 方法 方法定义

语法:

// 参数列表的参数类型不能省略
// 返回值类型可以省略,由 scala 编译器自动推断
// 定义递归方法,不能省略返回值类型
// 返回值可以不写 return,默认就是{}块表达式的值
def methodName (参数名:参数类型, 参数名:参数类型): [return type] = {
	// 方法体
}

使用:

def add(a: Int,b:Int) = a + b
方法参数
  • 默认参数
    在定义方法时可以给参数定义一个默认值。
// x, y带有默认值为0
def add(x:Int = 0, y:Int = 0) = x + y
println(add())
  • 带名参数
    在调用方法时,可以指定参数的名称来进行调用。
def add(x:Int = 0, y:Int = 0) = x + y
println(add(x = 1))
  • 变长参数
    如果方法的参数是不固定的(可以是0个或多个),可以定义一个方法的参数是变长参数。
// 语法:
def 方法名(参数名:参数类型*): 返回值类型 = {
	方法体
}

// 使用:
def add(num:Int*) = num.sum
println()  // 0
println(add(1, 2, 3, 4, 5))  // 15
方法调用方式
  • 后缀调用法
// 语法:
// 对象名.方法名(参数)

// 使用:
Math.abs(-1)
  • 中缀调用法
// 语法:
// 对象名 方法名 参数
// 如果有多个参数,使用括号括起来

// 使用:
Math abs -1
1 to 10
  • 所有的操作符都是方法,1 + 1 也就是中缀调用法
  • 如果有多个参数,使用括号括起来
  • 花括号调用法
// 语法:
// 对象名.方法名{
	// 表达式1
	// 表达式2
// }

// 使用:
Math.abs{
	println("求绝对值")
	-1
}

方法只有一个参数,才能使用花括号调用法

  • 无括号调用法
    如果方法没有参数,调用时可以省略方法名后面的括号
def printHello() = println("hello")
printHello
5.2 函数 定义函数
// 语法:
// val 函数变量名 = (参数名:参数类型, 参数名:参数类型......) => 函数体

// 使用:
val add = (x:Int, y:Int) => x + y
  • 函数是一个对象(变量)
  • 类似于方法,函数也有输入参数和返回值
  • 函数定义不需要使用 def 定义
  • 无需指定返回值类型,会自动推导
方法和函数的区别
  • 方法是隶属于类或者对象的,在运行时,它是加载到 JVM 的方法区中
  • 可以将函数对象赋值给一个变量,在运行时,它是加载到 JVM 的堆内存中
  • 函数是一个对象,继承自 FunctionN,函数对象有 apply,curried,toString、tupled 这些方法。方法则没有
方法转换为函数

用法:使用 _ 即可将方法转换为函数

def add(x:Int, y:Int) = x + y
val a = add _
偏函数
  • 偏函数被包在花括号内没有 match 的一组 case 语句是一个偏函数
  • 偏函数是 PartialFunction[A, B] 的一个实例
    • A 代表输入参数类型
    • B 代表返回结果类型
// 例子一:
// 1. 定义一个偏函数
val partialFunction:PartialFunction[Int, String] = {
	case 1 => "一"
	case 2 => "二"
	case 3 => "三"
	case _ => "其他"
}
// 2. 调用偏函数
println(partialFunction(1))
println(partialFunction(2))
println(partialFunction(3))
println(partialFunction(4))

// 例子二:
// 1. 定义一个列表  1-10
val list = (1 to 10).toList

// 2. 使用集合函数式操作来进行数据的转换
val stringList = list.map{
	case x if x >= 1 && x <= 3 => "[1-3]"
	case x if x >= 4 && x <= 8 => "[4-8]"
	case _ => "(8, *)"
}
println(stringList)  // List([1-3], [1-3], [1-3], [4-8], [4-8], [4-8], [4-8], [4-8], (8, *), (8, *))
六、集合 6.1 数组 定长数组
  • 定长数组指的是数组的长度是不允许改变的
  • 数组的元素是可以改变的
// 语法:
// 1. 通过指定长度定义数组
// val/var 变量名 = new Array[元素类型](数组长度)
// 2. 用元素直接初始化数组
//val/var 变量名 = Array(元素1, 元素2, 元素3,...)

// 使用1:
val a = new Array[Int](100)
a(0) = 100
// 使用2:
val a = Array("java", "scala", "python")
println(a.length)
  • 在 Scala 中,数组的泛型使用 [ ] 来指定
  • 使用 () 来获取元素
变长数组

变长数组指的是数组的长度是可变的,可以往数组中添加、删除元素。

  • 定义变长数组
    创建变长数组,需要提前导入 ArrayBuffer 类import scala.collection.mutable.ArrayBuffer
// 语法:
// 1. 创建空的ArrayBuffer变长数组
// val/var a = ArrayBuffer[元素类型]()
// 2. 创建带有初始元素的ArrayBuffer
// val/var a = ArrayBuffer(元素1, 元素2, 元素3,...)

// 使用1:
val a = ArrayBuffer[Int]()
// 使用2:
val a = ArrayBuffer("hadoop", "storm", "spark")
  • 添加/修改/删除元素
    • 使用 += 添加元素
    • 使用 -= 删除元素
    • 使用 ++= 追加一个数组到变长数组
val a = ArrayBuffer("hadoop", "storm", "spark")
// 追加一个元素
a += "flume"  // ArrayBuffer(hadoop, storm, spark, flume)
// 删除一个元素
a -= "hadoop"  // ArrayBuffer(storm, spark, flume)
// 追加一个数组
a ++= Array("hive", "sqoop")  // ArrayBuffer(storm, spark, flume, hive, sqoop)
// 修改数组中的元素
a(0) = "s"  // ArrayBuffer(s, spark, flume, hive, sqoop)
遍历数组
  • 使用 for 表达式,直接遍历数组中的元素
val a = Array(1, 2, 3, 4, 5)
for(i <- a) println(i)
  • 使用索引遍历数组中的元素
val a = Array(1, 2, 3, 4, 5)
for(i <- 0 to a.length - 1) println(a(i))
for(i <- 0 until a.length) println(a(i))
数组的常用算法
val a = Array(4, 1, 2, 4, 10)
// 求和
println(a.sum)  // 21
// 求最大值
println(a.max)  // 10
// 求最小值
println(a.min)  // 1
// 排序
// 1. 升序排序
println(a.sorted.toList)  // List(1, 2, 4, 4, 10)
// 2. 反转
println(a.sorted.reverse.toList)  // List(10, 4, 4, 2, 1)
6.2 元组

元组可以用来包含一组不同类型的值,元组的元素是不可变的。

定义元组
// 语法:
// 1. 使用括号来定义元组
// val/var 元组 = (元素1, 元素2, 元素3,...)
// 2. 使用箭头来定义元组(元组只有两个元素)
// val/var 元组 = 元素1 -> 元素2

// 使用1:
val a = (1, "linghuchong", 25, "华山派")
// 使用2:
val a = "linghuchong" -> 25  // (linghuchong,25)
val a = "linghuchong" -> 25 -> "华山派"  // ((linghuchong,25),华山派)
访问元组
// 使用_1、_2、_3...来访问元组中的元素

val a = "linghuchong" -> 25
// 获取第一个元素
a._1  // linghuchong
6.3 列表

列表是 Scala 中最重要的、也是最常用的数据结构。

  • 列表可以保存重复的值
  • 有先后顺序
不可变列表

不可变列表就是列表的元素、长度都是不可变的。

// 语法:
// 1. 使用List(元素1, 元素2, 元素3,...)来创建一个不可变列表
// val/var 变量名 = List[列表类型]()
// val/var 变量名 = List(元素1, 元素2, 元素3,...)
// 2. 使用Nil创建一个不可变的空列表
// val/var 变量名 = Nil
// 3. 使用::方法创建一个不可变列表
// val/var 变量名 = 元素1::元素2::Nil

// 使用1:
val a = List(1, 2, 3, 4)
// 使用2:
val a = Nil
// 使用3:
val a = -2 :: -1 ::Nil
可变列表
  • 定义
    可变列表就是列表的元素、长度都是可变的。要使用可变列表,先要导入import scala.collection.mutable.ListBuffer
// 语法:
// 1. 使用ListBuffer[元素类型]()创建空的可变列表
// val/var 变量名 = ListBuffer[Int]()
// 2. 使用ListBuffer(元素1, 元素2, 元素3,...)创建可变列表
// val/var 变量名 = ListBuffer(元素1, 元素2, 元素3,...)

// 使用1:
val a = ListBuffer[Int]()
// 使用2:
val a = ListBuffer(1, 2, 3, 4)
  • 可变集合都在 mutable 包中
  • 不可变集合都在 immutable 包中(默认导入)
  • 可变列表操作
    • 获取元素(使用括号访问(索引值))
    • 添加元素(+=)
    • 追加一个列表(++=)
    • 更改元素(使用括号获取元素,然后进行赋值)
    • 删除元素(-=)
    • 转换为List(toList)
    • 转换为Array(toArray)
val a = ListBuffer(1, 2, 3)
// 获取第一个元素
a(0)  // 1
// 添加元素 4
a += 4  // ListBuffer(1, 2, 3, 4)
// 追加一个列表,该列表包含(5, 6, 7)
a ++= List(5, 6, 7)  // ListBuffer(1, 2, 3, 4, 5, 6, 7)
// 删除元素 7
a -= 7  // ListBuffer(1, 2, 3, 4, 5, 6)
// 将可变列表转换为不可变列表
println(a.toList)  // List(1, 2, 3, 5, 6, 7)
// 将可变列表转换为数组
println(a.toArray)
列表常用操作
  • 判断列表是否为空(isEmpty)
  • 拼接两个列表(++)
  • 获取列表的首个元素(head)和剩余部分(tail)
  • 反转列表(reverse)
  • 获取前缀(take)、获取后缀(drop)
  • 扁平化(flatten)
  • 拉链(zip)和拉开(unzip)
  • 转换字符串(toString)
  • 生成字符串(mkString)
  • 并集(union)
  • 交集(intersect)
  • 差集(diff)
val a = List(1, 2, 3)
val b = List(4, 5, 6)
val c = List(List(1, 2), List(3), List(4, 5))
// 判断列表是否为空
a.isEmpty  // false
// 拼接两个列表
a ++ b  // List(1, 2, 3, 4, 5, 6)
// 获取列表的首个元素
a.head  // 1
// 获取列表的剩余部分
a.tail  // List(2, 3)
// 反转列表
println(a.reverse)  // List(3, 2, 1)
// 获取前缀:获取包含前n个元素的列表
a.take(2)  // List(1, 2)
// 获取后缀:获取不包含前n个元素的列表
a.drop(2)  // List(3)
// 扁平化(压平):将列表中的列表中的所有元素放到一个列表中
c.flatten  // List(1, 2, 3, 4, 5)
// 拉链:将两个列表组合成一个元素为元组的列表
val names = List("linghuchong", "renyingying", "yuelingshan")
val ages = List(25, 18, 18)
val res = names.zip(ages)  // List((linghuchong,25), (renyingying,18), (yuelingshan,18))
// 拉开:将一个包含元组的列表,解开成包含两个列表的元组
res.unzip  // (List(linghuchong, renyingying, yuelingshan),List(25, 18, 18))
// 转换字符串
a.toString  // List(1, 2, 3)
// 生成字符串:将元素以分隔符拼接起来,默认没有分隔符
a.mkString  // 123
a.mkString(":")  // 1:2:3

val a = List(1, 2, 3, 4)
val b = List(3, 4, 5, 6)
// 并集:不去重
a.union(b)  // List(1, 2, 3, 4, 3, 4, 5, 6)
a.union(b).distinct  // List(1, 2, 3, 4, 5, 6)
// 交集:
a.intersect(b)  // List(3, 4)
// 差集:
// 获取a在b中不存在的元素
a.diff(b)  // List(1, 2)
6.4 集合

Set(集)是代表没有重复元素的集合。

  • 元素不重复
  • 不保证插入顺序
不可变集
  • 定义
// 语法:
// 1. 创建一个空的不可变集
// val/var 变量名 = Set()
// val/var 变量名 = Set[类型]()
// 2. 给定元素来创建一个不可变集
// var/var 变量名 = Set(元素1, 元素2, 元素3,...)

// 使用1:
val a = Set[Int]()
// 使用2:
val a = Set(1, 2, 3, 4, 5)
  • 基本操作
    • 获取集的大小(size)
    • 遍历集(和遍历数组一样)
    • 添加一个元素,生成一个Set(+)
    • 拼接两个集,生成一个Set(++)
    • 拼接集合列表,生成一个Set(++)
val a = Set(1, 1, 2, 3, 4, 5)
// 获取集的大小
a.size  // a.size
// 遍历集
for(i <- a) println(i)  // 5 1 2 3 4
// 删除元素1
a - 1  // Set(5, 2, 3, 4)
// 添加元素1
a + 1  // Set(5, 1, 2, 3, 4)
// 拼接另一个集
a ++ Set(6 ,7 ,8)  // Set(5, 1, 6, 2, 7, 3, 8, 4)
// 拼接一个列表
a ++ List(6, 7, 8, 9)  // Set(5, 1, 6, 9, 2, 7, 3, 8, 4)
可变集

可变集和不可变集的创建方式一致,只不过需要提前导入一个可变集类。要使用可变集,先要导入import scala.collection.mutable.Set

val a = Set(1, 2, 3, 4)
// 添加元素5
a += 5  // Set(1, 5, 2, 3, 4)
// 移除元素1
a -= 1  // Set(5, 2, 3, 4)
6.5 映射

Map 可以称为映射,它是由键值对组成的集合。在 Scala 中,Map 也分为不可变 Map 和 可变 Map。

  • 不可变 Map
// 语法:
// val/var map = Map(键->值, 键->值, 键->值...)  // 推荐,可读性更好
val/var map = Map((键, 值), (键, 值), (键, 值)...)

// 使用:
val a = Map("zhangsan"->30, "lisi"->40)
val b = Map(("zhangsan", 30), ("lisi", 40))
a("zhangsan")  // 30
  • 可变 Map
    定义语法与不可变 Map 一致,但定义可变 Map 需要手动导入import scala.collection.mutable.Map
val a = Map("zhangsan"->30, "lisi"->40)
a("zhangsan") = 20
a("zhangsan")  // 20
6.6 Option 类型

使用 Option 类型,可以用来有效避免空指针(null)异常。将来我们返回某些数据时,可以返回一个 Option 类型来替代。

在 Scala 中,Option 类型来表示可选值。这种类型的数据有两种形式:

  • Some(x):表示实际的值
  • None:表示没有值
  • 使用 getOrElse 方法,当值为 None 时可以指定一个默认值
// 1. 定义一个相除的方法,使用Option来封装数据
def div(x:Double, y:Double) = {
	if(y == 0) {
		None  // 表示没有数据
	} else {
		val result = x / y
		Some(result)  // Some表示有数据
	}
}

// 2. 可以使用模式匹配来判断是否有值
val some = div(10.0, 2.0)
val none = div(10.0, 0)

none match {
	case Some(x) => println(x)
	case None => println("除零异常")
}

// 使用getOrElse来获取Option类型的值
println(some.getOrElse(0))
println(none.getOrElse(0))
6.7 iterator 迭代器

Scala 针对每一类集合都提供了一个迭代器(iterator)用来迭代访问集合。

  • 使用迭代器遍历集合
    • 使用 iterator 方法可以从集合获取一个迭代器
    • 迭代器的两个基本操作
      • hasNext——查询容器中是否有下一个元素
      • next——返回迭代器的下一个元素,如果没有,抛出 NoSuchElementException
    • 每一个迭代器都是有状态的
      • 迭代完后保留在最后一个元素的位置
      • 再次使用则抛出 NoSuchElementException
    • 可以使用 while 或者 for 来逐个返回元素
val a = List(1, 2, 3, 4, 5)
val ite = a.iterator
// while循环
while(ite.hasNext) {
	println(ite.next)
}
// for表达式
// 因为上一个ite已经到了最后一个状态,所以只能重新获取一个迭代器
val ite = a.iterator
for(i<-ite) println(i)
七、函数式编程 7.1 遍历(foreach)
// 方法签名:
// foreach(f: (A) => Unit): Unit

val a = List(1, 2, 3, 4)
// 使用:
a.foreach((x:Int) => println(x))
// 使用类型推断简化函数定义
a.foreach(x => println(x))
// 使用下划线来简化函数定义:要求1.只在函数体中出现一次2.函数体没有嵌套调用
a.foreach(println(_))
7.2 映射(map)

map 方法接收一个函数,将这个函数应用到每一个元素,返回一个新的列表。

// 方法签名:
// def map[B](f: (A) => B): TraversableOnce[B]

val a = List(1, 2, 3, 4)
// 使用:
a.map(x => x + 1)  // List(2, 3, 4, 5)
a.map(_ + 1)
7.3 映射扁平化(flatmap)

可以把 flatMap 理解为先 map、然后再 flatten。

// 方法签名:
// def flatMap[B](f: (A) => GenTraversableOnce[B]: TraversableOnce[B])

val a = List("hadoop hive spark flink flume", "kudu hbase sqoop storm")
// 使:1:先map后flatten
val list = a.map(_.split(" "))
list.flatten
// 使用2:flatMap
a.flatMap(_.split(" "))
7.4 过滤(filter)
// 方法签名:
// def filter(p: (A) => Boolean): TraversableOnce[A]

val a = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
// 使用:
a.filter(_ % 2 == 0)
7.5 是否存在(exists) 7.6 排序(sorted、sortBy、sortWith)
  • 默认排序 sorted
val a = List(3, 1, 2, 9, 7)
a.sorted  // List(1, 2, 3, 7, 9)
  • 指定字段排序 sortBy
// 方法签名:
// def sortBy[B](f: (A) => B): List[A]

val a = List("01 hadoop", "02 flume", "03 hive", "04 spark")
// 使用:
a.sortBy(_.split(" ")(1))  // List(02 flume, 01 hadoop, 03 hive, 04 spark)
  • 自定义排序 sortWith
// 方法签名:
// def sortWith(lt: (A, A) => Boolean): List[A]

val a = List(2, 3, 1, 6, 4, 5)
// 使用:
a.sortWith((x, y) => if (x > y) true else false)  // List(6, 5, 4, 3, 2, 1)
a.sortWith(_ > _)  //List(6, 5, 4, 3, 2, 1)
7.7 分组(groupBy)
// 方法签名:
// def groupBy[K](f: (A) => K): Map[K, List[A]]

val a = List("令狐冲" -> "华山派", "岳灵珊" -> "华山派", "任盈盈" -> "日月神教", "任我行" -> "日月神教")
// 使用:
a.groupBy(x => x._2)  // Map(华山派 -> List((令狐冲,华山派), (岳灵珊,华山派)), 日月神教 -> List((任盈盈,日月神教), (任我行,日月神教)))
a.groupBy(_._2)
7.8 聚合计算(reduce)
// 方法签名:
// def reduce[A1 >: A](op: (A1, A1) => A1): A1

val a = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 使用:
a.reduce((x, y) => x + y)  // 55
a.reduce(_ + _)
  • reduce 和 reduceLeft 效果一致,表示从左到右计算
  • reduceRight 表示从右到左计算
7.9 折叠(fold)
// 方法签名:
// def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1

val a = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 使用:
a.fold(0)((x, y) => x + y)  // 155
a.fold(100)(_ + _)
  • fold 和 foldLeft 效果一致,表示从左往右计算
  • fold 和 Right 表示从右往左计算
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/279371.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号