四天掌握Scala(3)

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
简介: 你好看官,里面请!今天笔者讲的是scala。不懂或者觉得我写的有问题可以在评论区留言,我看到会及时回复。 注意:本文仅用于学习参考,不可用于商业用途,如需转载请跟我联系。

四天掌握Scala(3)

1.9 方法调用方式

在 Scala 中,有以下几种方法调用方式,后缀调用法、中缀调用法、花括号调用法、无括号调用法,在后续编写 Spark、Flink 程序时,会使用到这些方法调用方式。

1.9.1 后缀调用法

这种方法与 Java 没有区别。

语法:

对象名.方法名(参数)

示例: 使用后缀法 Math.abs 求绝对值。

参考代码

scala> Math.abs(-1)
res10: Int = 1
scala> Math.abs(-3)
res11: Int = 3

1.9.2 中缀调用法

语法

对象名 方法名 参数
1 to 10 //如果有多个参数,使用括号括起来

示例: 使用中缀法 Math.abs 求绝对值。

scala> Math abs -3
res12: Int = 3

1.9.3 操作符即方法

来看一个表达式:

1 + 1

大家觉得上面的表达式像不像方法调用?在Scala 中,+ - * / % 等这些操作符和 Java 一样,但在 Scala 中,所有的操作符都是方法,操作符是一个方法名字是符号的方法。

1.9.4 花括号调用法

语法格式如下:

Math.abs{ 
    // 表达式1
    // 表达式2
}

方法只有一个参数,才能使用花括号调用法,因为块表达式只有一个返回值,所以只能给1个参数用。示例: 使用花括号调用法 Math.abs 求绝对值。参考代码如下:

scala> Math.abs{-10}
res13: Int = 10

1.9.5 无括号调用法

如果方法没有参数,可以省略方法名后面的括号。示例如下:

  1. 定义一个无参数的方法,打印 “hello amo”。
  2. 使用无括号调用法调用该方法。

参考代码:

scala> def m3()=println("hello amo")
m3: ()Unit
scala> m3()
hello amo

1.10 函数 – 重点掌握

Scala 支持函数式编程,编写 Spark/Flink 程序中,会大量使用到函数。函数和我们的对象一样, 在 Scala 中都是属于一等公民。

1.10.1 定义函数

简便语法:

val 函数变量名 = (参数名:参数类型, 参数名:参数类型....) => 函数体

函数是一个 对象(变量)。 类似于方法,函数也有输入参数和返回值,函数定义不需要使用 def 定义,无需指定返回值类型。

示例:

  1. 定义一个两个数值相加的函数。
  2. 调用该函数。

参考代码:

scala> val add = (x:Int, y:Int) => x + y
add: (Int, Int) => Int = <function2>
scala> add(1,2)
res3: Int = 3

1.10.2 方法和函数的区别

方法是隶属于类或者对象的,在运行时,它是加载到 JVM 的方法区中。但是函数本身就是一个对象,可以将函数对象赋值给一个变量,在运行时,它是加载到 JVM 的堆内存中,函数是一个对象,继承自 FunctionN,函数对象有 apply,curried,toString,tupled 这些方法,方法则没有。通俗来说,从定义的方式就可以看出方法和函数的区别:

  1. 一般我们使用 def 定义的为方法。
  2. 而通过 val 或者 var 定义一个对象来接收的,一般就是函数。
  3. 因为方法无法赋值给对象,但是函数定义的时候,就是直接赋值给了对象的。

示例: 方法无法赋值给变量。

scala> def add(x:Int, y:Int)=x+y
add: (x: Int, y: Int)Int
scala> val a = add
<console>:18: error: missing argument list for method add
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `add _` or `add(_,_)` instead of `add`.
       val a = add
               ^
scala>

1.10.3 方法转换为函数

有时候需要将方法转换为函数,作为变量传递,就需要将方法转换为函数。使用 _ 即可将方法转换为函数。

示例:

  1. 定义一个方法用来进行两个数相加。
  2. 将该方法转换为一个函数,赋值给变量。

参考代码:

scala> def add(x:Int,y:Int)=x+y
add: (x: Int, y: Int)Int
scala> val a = add _
a: (Int, Int) => Int = $Lambda$1375/1645141562@34696884

不用过多去思考为何加了一个 _ 就能转换成函数,这里没有什么特殊的意思,就是语法要求而已。

1.10.4 完全体函数

前面写的函数,实际上是一种省略了返回值的写法,完全体如下:

val func: (Int, Int) => Int = (x, y) => x + y

其中:前面的 (Int, Int) => Int 是对象 func(也就是这个函数)的类型,类型是一个函数,函数的内容格式是两个 int 参数输入,返回一个 int 输出,后面的 (x, y) => x + y 就是定义形参,给形参命名,同时写上函数体,一般我们不写完全体,简略体就够了。容易混淆的错误写法:

scala> val addFunc: Int = (x:Int, y:Int) => x + y
<console>:17: error: type mismatch;
 found   : (Int, Int) => Int
 required: Int
       val addFunc: Int = (x:Int, y:Int) => x + y

对函数 addFunc 的类型定义错误,addFunc 是一个函数,函数的类型必须是能看出什么输入 + 得到什么输出,也就是这里 addFunc 的类型应该是 (Int, Int) => Int 也就是,两个 Int 输入参数,得到一个 Int 输出返回。

1.11 数组 – 重点掌握

Scala 中数组的概念是和 Java 类似,可以用数组来存放一组数据。Scala 中,有两种数组,一种是 定长数组,另一种是 变长数组。

1.11.1 定长数组

  1. 定长数组指的是数组的 长度不允许改变 的。
  2. 数组的 元素可以改变 的。

java 中数组是根据类型来定义的比如 int[] String[],在 Scala 中, 数组也是一个类,Array 类,存放的内容通过泛型来定义,类似 java 中 List 的定义,语法格式如下:

// 通过指定长度定义数组
val/var 变量名 = new Array[元素类型](数组长度)
// 用元素直接初始化数组
val/var 变量名 = Array(元素1, 元素2, 元素3...)

在 Scala 中,数组的泛型使用 [] 来指定(java <>),使用 () 来获取元素(java []),这两点要注意,不要混淆了。

示例1:

  1. 定义一个长度为 100 的整型数组。
  2. 设置第 1 个元素为 110。
  3. 打印第 1 个元素。

参考代码:

scala> val a = new Array[Int](100)
scala> a(0) = 110
scala> println(a(0))
110

示例2:

  1. 定义一个包含以下元素的数组: java、scala、python。
  2. 获取数组长度。

参考代码:

// 定义包含jave、scala、python三个元素的数组
scala> val a = Array("java","scala","python")
a: Array[String] = Array(java, scala, python)
scala> a.length
res18: Int = 3

为什么带初值的就不用 new 呢,这里会用到一个 apply 方法,后面会详细说。现在只需要知道,直接 Array(1, 2, 3) 来创建数组,其实就是自动调用了 Array 类中的 apply 方法,apply 方法做的事情就是,new array(3) 然后把 3 个元素放进去,也就是这些工作自动帮我们做了。

1.11.2 变长数组

变长数组指的是数组的长度是可变的,可以往数组中添加、删除元素。定义变长数组,创建变长数组,需要提前导入 ArrayBuffer 类 import scala.collection.mutable.ArrayBuffer

语法:

创建空的 ArrayBuffer 变长数组,语法结构:

val/var a = ArrayBuffer[元素类型]()

创建带有初始元素的 ArrayBuffer

val/var a = ArrayBuffer(元素1,元素2,元素3....)

示例1: 定义一个长度为0的整型变长数组

参考代码:

val a = ArrayBuffer[Int]()

为什么长度为 0 的就必须加泛型呢? 如果不加就是下面这样:

image.png

因为没有初值来判断泛型, 所以泛型是 Nothing,同时不要忘记省略(),不要用方法调用的概念认为不带参数就可以不写括号了, 这样是不可以的,如下:

image.png

就像前面提过一句的 apply 方法,如果不带(),那么就不会调用 apply 方法,不调用 apply 方法,那么就没有 ArrayBuffer 的调用,也就是不知道调用谁了。

示例2: 定义一个包含以下元素的变长数组。

"hadoop", "storm", "spark"

参考代码

scala> var a2 = ArrayBuffer("hadoop", "storm", "spark")
a2: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer(hadoop, storm, spark)

添加/修改/删除元素。 使用 += 添加元素、使用 -= 删除元素、使用 ++= 追加一个数组到变长数组。

示例:

  1. 定义一个变长数组,包含以下元素: “hadoop”、“spark”、“flink”。
  2. 往该变长数组添加一个 “flume” 元素。
  3. 从该变长数组删除 “hadoop” 元素。
  4. 再将一个数组,该数组包含 “hive”, “sqoop” 追加到变长数组中。

参考代码

scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer
scala> val a = ArrayBuffer("hadoop", "spark", "flink")
a: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer(hadoop, spark, flink)
scala> a += "flume"
res19: a.type = ArrayBuffer(hadoop, spark, flink, flume)
scala> a -= "hadoop"
res20: a.type = ArrayBuffer(spark, flink, flume)
scala> val a2 = ArrayBuffer("hive", "sqoop")
a2: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer(hive, sqoop)
scala> a ++= a2
res21: a.type = ArrayBuffer(spark, flink, flume, hive, sqoop)

1.11.3 遍历数组

可以使用以下两种方式来遍历数组:

  1. 使用 for表达式 直接遍历数组中的元素。
  2. 使用 索引 遍历数组中的元素。

示例1:

  1. 定义一个数组,包含以下元素 1,2,3,4,5。
  2. 使用 for 表达式直接遍历,并打印数组的元素。

参考代码

scala> val a = Array(1,2,3,4,5)
a: Array[Int] = Array(1, 2, 3, 4, 5)
scala> for(i <- a) println(i)
1
2
3
4
5

示例2:

  1. 定义一个数组,包含以下元素1,2,3,4,5。
  2. 使用 for 表达式基于索引下标遍历,并打印数组的元素。

参考代码

scala> val a = Array(1,2,3,4,5)
a: Array[Int] = Array(1, 2, 3, 4, 5)
scala> for(i <- 0 until a.length) print(a(i))
12345
scala> for(i <- 0 to a.length-1) print(a(i))
12345

0 until n——生成一系列的数字,包含0,不包含n,0 to n ——包含0,也包含n。

1.11.4 数组常用算法

Scala 中的数组封装了一些常用的计算操作,将来在对数据处理的时候,不需要我们自己再重新实现。以下为常用的几个算法:求和——sum方法、求最大值——max方法、求最小值——min方法、排序——sorted方法

求和: 数组中的 sum 方法可以将所有的元素进行累加,然后得到结果。

示例:

  1. 定义一个数组,包含以下几个元素(1,2,3,4)。
  2. 请计算该数组的和。

参考代码:

scala> val a = Array(1,2,3,4)
a: Array[Int] = Array(1, 2, 3, 4)
scala> a.sum
res26: Int = 10

最大值: 数组中的 max 方法,可以获取到数组中的最大的那个元素值。

示例:

  1. 定义一个数组,包含以下几个元素(4,1,2,4,10)。
  2. 获取数组的最大值。

参考代码:

scala> val a = Array(4,1,2,4,10)
a: Array[Int] = Array(4, 1, 2, 4, 10)
scala> a.max
res27: Int = 10
scala> a.min
res28: Int = 1
scala> a.reverse
res29: Array[Int] = Array(10, 4, 2, 1, 4)
scala> a.sorted
res30: Array[Int] = Array(1, 2, 4, 4, 10)
scala> a.sorted.reverse
res31: Array[Int] = Array(10, 4, 4, 2, 1)

1.12 元组 – 重点掌握

元组可以用来包含一组不同类型的值。例如:姓名,年龄,性别,出生年月。元组的元素是不可变的。数组: 同一类数据成组。元组: 不同的元素成组,并且元组内容(元素)不可变。

1.12.1 定义元组

语法

方式1: 使用括号来定义元组

val/var 元组 = (元素1, 元素2, 元素3....)

方式2:使用箭头来定义元组(元组只能有两个元素)

val/var 元组 = 元素1->元素2

示例1: 定义一个元组,包含一个学生的以下数据。

id 姓名 年龄 地址
1 amo 18 chengdu

参考代码

scala> val a = (1,"amo",18,"chengdu")
a: (Int, String, Int, String) = (1,amo,18,chengdu)

示例2: 定义一个元组,包含学生的姓名和年龄(paul、26)、分别使用括号、和箭头来定义元组。

参考代码:

scala> val a = ("paul", 26)
a: (String, Int) = (paul,26)
scala>
scala> val b = "paul" -> 20
b: (String, Int) = (paul,20)

1.12.2 访问元组

使用 _1、_2、_3… 来访问元组中的元素,_1 表示访问第一个元素,依次类推。

示例: 定义一个元组,包含一个学生的姓名和性别,“crystal”, “female”,分别获取该学生的姓名和性别。

参考代码

scala> val b = "paul" -> 20
b: (String, Int) = (paul,20)
scala> val a = "crystal" -> "female"
a: (String, String) = (crystal,female)
scala> a._1
res32: String = crystal
scala> a._2
res33: String = female

1.13 列表 – List – 重点掌握

列表是 Scala 中最重要的、也是最常用的数据结构。List 具备以下性质:

  1. 可以保存重复的值。
  2. 有先后顺序。

在 Scala 中,也有两种列表,一种是不可变列表、另一种是可变列表。

相关实践学习
基于Hologres轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
Linux入门到精通
本套课程是从入门开始的Linux学习课程,适合初学者阅读。由浅入深案例丰富,通俗易懂。主要涉及基础的系统操作以及工作中常用的各种服务软件的应用、部署和优化。即使是零基础的学员,只要能够坚持把所有章节都学完,也一定会受益匪浅。
相关文章
|
1月前
|
Java Unix Scala
Scala 安装
Scala 安装
35 3
|
7月前
|
并行计算 前端开发 安全
Scala
Scala
56 0
|
7月前
|
分布式计算 Java 大数据
Scala01 —— Scala基础
Scala 是一种基于 JVM 的多范式编程语言,它融合了面向对象和函数式编程的特点。本文档介绍了Scala的基础知识,包括如何搭建开发环境、语言特性、变量和数据类型、程序逻辑、运算符、控制流、集合以及方法和函数的使用。特别强调了Scala集合的重要性,它们作为数据结构支持多种操作,并且有许多内置的算子和库来解决问题。文档还涵盖了如何在IDEA中配置Scala SDK,以及如何使用元组、映射、数组和模式匹配等核心概念。此外,文档还讨论了Scala与Java变量的区别,以及如何通过隐式类和字符串插值等扩展语言功能。
62 6
Scala01 —— Scala基础
|
Scala 索引 容器
四天掌握Scala(4)
你好看官,里面请!今天笔者讲的是scala。不懂或者觉得我写的有问题可以在评论区留言,我看到会及时回复。 注意:本文仅用于学习参考,不可用于商业用途,如需转载请跟我联系。
135 1
四天掌握Scala(4)
|
Java 编译器 Scala
四天掌握Scala(2)
你好看官,里面请!今天笔者讲的是scala。不懂或者觉得我写的有问题可以在评论区留言,我看到会及时回复。 注意:本文仅用于学习参考,不可用于商业用途,如需转载请跟我联系。
148 1
四天掌握Scala(2)
|
SQL Java 大数据
四天掌握Scala(1)
你好看官,里面请!今天笔者讲的是scala。不懂或者觉得我写的有问题可以在评论区留言,我看到会及时回复。 注意:本文仅用于学习参考,不可用于商业用途,如需转载请跟我联系。
201 0
四天掌握Scala(1)
|
Java Scala
【Scala】Scala之Numbers(二)
 前面已经学习了Scala中的String,接着学习Scala的Numbers。
194 0
【Scala】Scala之Numbers(二)
|
Java Scala
【Scala】Scala之Numbers(一)
 前面已经学习了Scala中的String,接着学习Scala的Numbers。
158 0
【Scala】Scala之Numbers(一)
|
分布式计算 JavaScript 前端开发
Scala 必知必会
Scala 必知必会 3
120 0
Scala 必知必会
|
分布式计算 Scala Spark
scala中的self =>
scala中的self =>
188 0