Scala
scala安装
#编译运行scala程序,需要: JDK(jvm) Scala编译器(scala SDK)
安装JDK (java解释器)
#安装JDK 1.8 64位, 并配置环境变量.
安装Scala SDK (scala解释器)
#安装Scala SDK windows : scala-2.12.1.msi Linux : scala-2.11.12.tar.gz 安装完毕之后,测试是否安装成功: scala -version
安装IDEA插件
#先下载idealU #然后再下载Idealu支持Scala的插件 具体步骤占时略
概念
scala简介
//scala 运行在Jvm上这点和Java一样。 Scala是多范式编程语言。 //scala支持面向对象和函数式编程。 //scala刚刚问世的时候是个不起眼的小语种。但是随着Spark,Kafka等基于Scala的大数据框架的兴起,Scala就火了呀。 //scala的优势是它的表达性。
为什么使用Scala?
//开发大数据应用(Spark, Flink) //表达能力强,一行抵得上java多行 //兼容java,可以访问庞大的Java类库。例如Mysql, redies, freemrker activemq 等
Scala和Java对比
//java代码比较繁琐, Scala代码比较简洁. (三行Scala抵得上三十四行Java. 夸张的说!) //批量操作,scala一行map就差不多够了,可是Java需要便利循环处理
Scala编译执行过程
java程序是如何编译.执行的?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kG0zE3s7-21)(scala.assets/image-.png)]
scala程序是如何编译,执行的?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IHPPUNlx-23)(scala.assets/image-.png)]
// java编译器和scala编译器不通用哦. // scala也有自己的类库, scala也可以使用java类库哦. // scala
基础
交互式,文件式例子
交互式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-grLBWoIS-23)(scala.assets/image-.png)]
文件式
//HelloWorld.scala 代码如下: object HelloWorld {
/* 这是我的第一个 Scala 程序 * 以下程序将输出'Hello World!' */ def main(args: Array[String]) {
println("Hello, world!") // 输出 Hello World } }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2dgHhZh3-24)(scala.assets/image-.png)]
语法需要注意
#1. 区分大小写 - Scala是大小写敏感的,这意味着标识Hello 和 hello在Scala中会有不同的含义。 #2. 类名 - 对于所有的类名的第一个字母要大写。如果需要使用几个单词来构成一个类的名称,每个单词的第一个字母要大写。 示例:class MyFirstScalaClass #3. 方法名称 - 所有的方法名称的第一个字母用小写。如果若干单词被用于构成方法的名称,则每个单词的第一个字母应大写。 示例:def myMethodName() #4. 程序文件名 - 程序文件的名称应该与对象名称完全匹配(新版本不需要了,但建议保留这种习惯)。保存文件时,应该保存它使用的对象名称(记住Scala是区分大小写),并追加".scala"为文件扩展名。 (如果文件名和对象名称不匹配,程序将无法编译)。 示例: 假设"HelloWorld"是对象的名称。那么该文件应保存为'HelloWorld.scala" #5. def main(args: Array[String]) - Scala程序从main()方法开始处理,这是每一个Scala程序的强制程序入口部分。
Scala 变量
// 1.scala中var声明变量,val声明常量 val定义的变量不可以重新赋值,但是var定义的可以. // 2.Scala 可以使用类型推断。 val name = "占山"
惰性赋值
//当一些变量保存的数据较大时候,但是不需要马上加载到JVM内存中,可以使用惰性赋值来提高效率 当用到这个变量的时候,才会加载到JVM中 //语法: lazy val/var 变量名 = 表达式
例如有个复杂的Sql语言,我们希望只有用到SQL语句的时候才加载他.。 如果不使用lazy,就直接加载到内存了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EEWagGoH-24)(scala.assets/image-.png)]
数据类型
//scala中有着与java相同的数据类型。 如下说说与之不同的地方: scala中所有的类型都使用大写字母开头。 整形使用Int,而不是Integer scala 申请变量的时候可以不写类型,让scala编译器自己推断去吧。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tpEVg3jR-25)(scala.assets/image-.png)]
Scala类型层次结构
//Scala的数据类型也是“单根继承”体系, 都是继承Any这个类型 //AnyVal 是所有“值类型”的父类。 //AnyRef 是所有“引用类型”的父类 //Unit 表示“空类型” 他只有一个实例() 。它类似于java中的void, 但是scala比java更加的面向对象。 //Null 所有“引用类型”的子类。 也就是Nul类型可以赋值给所有“引用类型” //Nothing 所有类型的子类。 Nothing 表示方法抛出异常的时候,返回的子类。。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qauj3vwv-25)(scala.assets/image-.png)]
Null 类型是不可以赋值给 AnyVal 下面的类型的, 只可以赋值给AnyRef下的类型。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tJBvySMO-26)(scala.assets/image-.png)]
运算符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aCzNU0pw-26)(scala.assets/image-.png)]
条件表达式(if)
//if 的使用,语法和java一样。在此不多bb。 下面主要说和java不一样的地方: Scala中if是有返回值的。 Scala中没有三元表达式,可以使用if表达式代替 三元表达式
有返回值的if
例:当sex 是 “male”就返回1 , 否则就返回0
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2gq23e7w-27)(scala.assets/image-.png)]
块表达式
//scala中使用{} 表示块表达式 和if表示式一样,块表达式也是有值的。值就是最后一个表达式的值。 // 块表达式是很牛逼的一个东西。这玩意用的好,代码就精巧。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O0yxjpK9-27)(scala.assets/image-.png)]
循环
for
遍历循环1到9
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PStir5sz-28)(scala.assets/image-.png)]
在scala中,数字也是一个对象,也可以调用 .to方法。
//scala中 x.to(y) 相当于 python 中 range(x, y+1) // 1.to(10) 也可以写成 1 to 10
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3CUMIEne-28)(scala.assets/image-.png)]
for嵌套循环
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8AR7aK0Q-29)(scala.assets/image-.png)]
for的守卫
for表达式中,可以添加if判断语句,这个if判断就称之为守卫。我们可以使用守卫让for表达式更简洁。
语法:
for(i <- 表达式/数组/集合 if 表达式) {
// 表达式 } //表示,当if后面这个表达式式True的时候,才能进入下面的操作。
例:用for表达式打印1-10之间内 能整除3的数字
for(i <- 1.to(10) if(i%3==0)){
println(i) }
等价于:
for(i <- 1.to(10)){
if(i%3==0){
println(i) } }
for 的推导式
// 可以使用for推导式 生成一个心的集合(一组数据) // 我们把 使用yield的for表达式称之为“推导式”
例:生成10, 20, 30, … 100
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YDlFwySD-29)(scala.assets/image-.png)]
跟python的 v = [ i*10 for i in range(11)] 有点像哦。
while
略。
do … while
略。
break
* 在scala中,类似Java和C++的break/continue关键字被移除了 * 如果一定要使用break/continue,就需要使用scala.util.control包的Break类的breable和break方法。 * 导入Breaks包 import scala.util.control.Breaks._ * 使用breakable将for表达式包起来 * for表达式中需要退出循环的地方,添加`break()`方法调用
例:
// 导入scala.util.control包下的Break import scala.util.control.Breaks._ breakable{
for(i <- 1 to 100) {
if(i >= 50) break() else println(i) } }
continue
//continue的实现与break类似,但有一点不同: 实现break是用breakable{
}将整个for表达式包起来, 而实现continue是用breakable{
}将for表达式的循环体包含起来就可以了
例:打印1-100的数字,使用for表达式来遍历,如果数字能整除10,不打印
// 导入scala.util.control包下的Break import scala.util.control.Breaks._ for(i <- 1 to 100 ) {
breakable{
if(i % 10 == 0) break() else println(i) } }
方法,函数
Scala 有方法与函数,二者在语义上的区别很小。Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。换句话来说在类中定义的函数即是方法。 Scala 中的方法跟 Java 的类似,语法不一样,方法是组成类的一部分. Scala 中的函数则是一个完整的对象,Scala 中的函数其实就是继承了 Trait 的类的对象。 Scala 中使用 val 语句可以定义函数,def 语句定义方法。 注意:有些翻译上函数(function)与方法(method)是没有区别的。
方法
语法
def methodName (参数名:参数类型, 参数名:参数类型) : [return type] = {
// 方法体:一系列的代码 } /* * 参数列表的参数类型不能省略 * 返回值类型可以省略,由scala编译器自动推断 * 返回值可以不写return,默认就是{}块表达式的值 */
例:定义一个方法,实现两个整形数值相加,返回相加后的结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6MqCqlpd-90)(scala.assets/image-.png)]
标准写法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bB9fBOOr-91)(scala.assets/image-.png)]
返回值推断
//scala定义方法可以省略返回值,由scala自动推断返回值类型。这样方法定义后更加简洁。 //定义递归方法,不能省略返回值类型 //return 什么时候都可以不写,看你心情。
例:定义递归方法(求阶乘)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R2mn2JxF-92)(scala.assets/image-.png)]
方法的参数
scala中的方法参数,使用比较灵活。它支持以下几种类型的参数: - 默认参数 (和py一样) - 带名参数 (和py一样) - 变长参数 ( * )
1.默认参数:在定义方法时可以给参数定义一个默认值。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AXUIZ0qW-92)(scala.assets/image-.png)]
2.带名参数:在调用方法时,可以指定参数的名称来进行调用。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CecpdFQc-93)(scala.assets/image-.png)]
3.边长参数:如果方法的参数是不固定的,可以定义一个方法的参数是变长参数。
语法格式:
def 方法名(参数名:参数类型*):返回值类型 = {
方法体 } //在参数类型后面加一个`*`号,表示参数可以是0个或者多个
例子:定义一个计算若干个值相加的方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5rmKjRe2-94)(scala.assets/image-018151.png)]
输出:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j12uuZkv-94)(scala.assets/image-038011.png)]
疑问:不定长参数的类型式什么?猜想是数组。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2SNdvULt-95)(scala.assets/image-.png)]
输出:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YWdxewcX-95)(scala.assets/image-.png)]
答疑:是WrappendArray() ? 还是Seq[Int] ?
方法调用方式
//在scala中,有以下几种方法调用方式, 后缀调用法 中缀调用法 花括号调用法 无括号调用法 //在后续编写spark、flink程序时,我们会使用到这些方法调用方式。
1.后缀调用法
语法: 对象名.方法名(参数)
例:
Math.abs(-1) 1.to(10)
2.中缀调用法
语法: 对象名 方法名 参数 ; 如果有多个参数,使用括号括起来
例:
Math abs -1 1 to 10
3.花括号调用法
//方法只有一个参数,才能使用花括号调用法 Math.abs{
-10} //{}表示块表达式,快表达式的返回值就是最后一个表达式(之前说过,别忘了)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x5lavozL-96)(scala.assets/image-.png)]
4.无符号调用法
//如果方法没有参数,可以省略方法名后面的括号 def m3()=println("hello") m3
5.操作符也是方法
在scala中: 所有的操作符都是方法 操作符是一个方法名字是符号的方法. 1 + 1 这个表达式实际上也是一个方法调用哦。scala的特别之处,嘻嘻。 //下面不写不知道,一写么的吓一跳。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-70lgbz2i-96)(scala.assets/image-.png)]
函数
// scala支持函数是编程, 这个在编程Spark/flink程序中会大量使用,真特么重要。 /* 函数是一个 对象(变量) 类似于方法,函数也有输入参数和返回值 函数定义不需要使用def 定义 无需指定返回值类型 */
语法
val 函数变量名 = (参数名:参数类型, 参数名:参数类型....) => 函数体 猜想: 等价于python中 函数命=lambda 参数1,参数2 ... :函数体 (如:x = lambda x: x+1)
例:定义两个数值相加的函数
scala> val add = (x:Int, y:Int) => x + y add: (Int, Int) => Int = <function2> scala> add(1,2) res3: Int = 3
方法和函数的区别
/* 方法是隶属于类或者对象的,在运行时,它是加载到JVM的方法区中 可以将函数对象赋值给一个变量,在运行时,它是加载到JVM的堆内存中 函数是一个对象,继承自FunctionN,函数对象有apply,curried,toString,tupled这些方法。方法则没有 */
例:方法无法赋值给变量,函数可以
既: val 变量 = 函数名 ; 是正确的 此时 这个变量就是个函数。 val 变量 = 方法名 ; 是错误的 scala> val add1 = (x:Int, y:Int) => x+y add1: (Int, Int) => Int = $$Lambda$1092/@7b5833ee scala> add1 res14: (Int, Int) => Int = $$Lambda$1092/@7b5833ee scala> add1(1,1) res15: Int = 2 scala> val a1 = add1 a1: (Int, Int) => Int = $$Lambda$1092/@7b5833ee scala> a1(2,2) res16: Int = 4 // -------------------------------------------------------------------- scala> def add2(x:Int, y:Int) = x+y add2: (x: Int, y: Int)Int scala> add2(1,1) res18: Int = 2 scala> val a2 = add2 <console>:12: error: missing argument list for method add2 Unapplied methods are only converted to functions when a function type is expected. You can make this conversion explicit by writing `add2 _` or `add2(_,_)` instead of `add2`. val a2 = add2 ^
方法转化为函数
// 有时候需要将方法转换为函数,作为变量传递,就需要将方法转换为函数
语法:
val 变量 = 方法名 _
例:将方法转化为函数,赋值给变量
scala> def add(x:Int,y:Int)=x+y add: (x: Int, y: Int)Int scala> val a = add _ a: (Int, Int) => Int = <function2>
字符串(String)
//定义字符串方式 val S:String = "aaa" //使用双引号 val S:String = """aaaa""" //使用三引号 val S:String = s"${
name}你好" //使用插值表达式 //以s开头; name是个变量或者表达式
列出了 java.lang.String 常用方法
你可以在 Scala 中使用:
序号 | 方法及描述 |
---|---|
1 | char charAt(int index)返回指定位置的字符 |
2 | int compareTo(Object o)比较字符串与对象 |
3 | int compareTo(String anotherString)按字典顺序比较两个字符串 |
4 | int compareToIgnoreCase(String str)按字典顺序比较两个字符串,不考虑大小写 |
5 | String concat(String str)将指定字符串连接到此字符串的结尾 |
6 | boolean contentEquals(StringBuffer sb)将此字符串与指定的 StringBuffer 比较。 |
7 | static String copyValueOf(char[] data)返回指定数组中表示该字符序列的 String |
8 | static String copyValueOf(char[] data, int offset, int count)返回指定数组中表示该字符序列的 String |
9 | boolean endsWith(String suffix)测试此字符串是否以指定的后缀结束 |
10 | boolean equals(Object anObject)将此字符串与指定的对象比较 |
11 | boolean equalsIgnoreCase(String anotherString)将此 String 与另一个 String 比较,不考虑大小写 |
12 | byte getBytes()使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中 |
13 | byte[] getBytes(String charsetName使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中 |
14 | void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)将字符从此字符串复制到目标字符数组 |
15 | int hashCode()返回此字符串的哈希码 |
16 | int indexOf(int ch)返回指定字符在此字符串中第一次出现处的索引 |
17 | int indexOf(int ch, int fromIndex)返回在此字符串中第一次出现指定字符处的索引,从指定的索引开始搜索 |
18 | int indexOf(String str)返回指定子字符串在此字符串中第一次出现处的索引 |
19 | int indexOf(String str, int fromIndex)返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始 |
20 | String intern()返回字符串对象的规范化表示形式 |
21 | int lastIndexOf(int ch)返回指定字符在此字符串中最后一次出现处的索引 |
22 | int lastIndexOf(int ch, int fromIndex)返回指定字符在此字符串中最后一次出现处的索引,从指定的索引处开始进行反向搜索 |
23 | int lastIndexOf(String str)返回指定子字符串在此字符串中最右边出现处的索引 |
24 | int lastIndexOf(String str, int fromIndex)返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索 |
25 | int length()返回此字符串的长度 |
26 | boolean matches(String regex)告知此字符串是否匹配给定的正则表达式 |
27 | boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)测试两个字符串区域是否相等 |
28 | boolean regionMatches(int toffset, String other, int ooffset, int len)测试两个字符串区域是否相等 |
29 | String replace(char oldChar, char newChar)返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的 |
30 | String replaceAll(String regex, String replacement使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串 |
31 | String replaceFirst(String regex, String replacement)使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串 |
32 | String[] split(String regex)根据给定正则表达式的匹配拆分此字符串 |
33 | String[] split(String regex, int limit)根据匹配给定的正则表达式来拆分此字符串 |
34 | boolean startsWith(String prefix)测试此字符串是否以指定的前缀开始 |
35 | boolean startsWith(String prefix, int toffset)测试此字符串从指定索引开始的子字符串是否以指定前缀开始。 |
36 | CharSequence subSequence(int beginIndex, int endIndex)返回一个新的字符序列,它是此序列的一个子序列 |
37 | String substring(int beginIndex)返回一个新的字符串,它是此字符串的一个子字符串 |
38 | String substring(int beginIndex, int endIndex)返回一个新字符串,它是此字符串的一个子字符串 |
39 | char[] toCharArray()将此字符串转换为一个新的字符数组 |
40 | String toLowerCase()使用默认语言环境的规则将此 String 中的所有字符都转换为小写 |
41 | String toLowerCase(Locale locale)使用给定 Locale 的规则将此 String 中的所有字符都转换为小写 |
42 | String toString()返回此对象本身(它已经是一个字符串!) |
43 | String toUpperCase()使用默认语言环境的规则将此 String 中的所有字符都转换为大写 |
44 | String toUpperCase(Locale locale)使用给定 Locale 的规则将此 String 中的所有字符都转换为大写 |
45 | String trim()删除指定字符串的首尾空白符 |
46 | static String valueOf(primitive data type x)返回指定类型参数的字符串表示形式 |
补充:
S.head S.drop(n) S.dropRight(n) 删除后面n个字符
字符串长度
str.length()
判断是字符串子字串
//判断str2在str1中的位置 str1.indexOf(str2) 返回-1说明 不存在
字符串拼接
val str3 = str1.concat(str2) 或者 val str3 = str1 + str2
替换
str1.replaceAll("字符串1","字符串2") //将str1中 字符串1替换成字符串2
列表(List)
//列表是scala中最重要的、也是最常用的数据结构。List具备以下性质: - 可以保存重复的值 - 有先后顺序 //有两种列表,一种是不可变列表、另一种是可变列表
不可变列表
//不可变列表就是列表的元素、长度都是不可变的。 //实际上元素,长度都是可以变的。 其实是可以改变的,例如:updated(), drop(), 准确的说“不可变列表 只是长度不可以增加”
定义语法
//使用`List(元素1, 元素2, 元素3, ...)`来创建一个不可变列表: val/var 变量名 = List(元素1, 元素2, 元素3...) //例如 : var L = List(2,4,9,5,3,6,1,7,8) //使用`Nil`创建一个不可变的空列表: val/var 变量名 = Nil //使用`::`方法创建一个不可变列表 val/var 变量名 = 元素1 :: 元素2 :: Nil //使用::拼接方式来创建列表,必须在最后添加一个Nil
例:创建一个不可变列表,存放以下几个元素(1,2,3,4)
scala> val a = List(1,2,3,4) a: List[Int] = List(1, 2, 3, 4)
例:使用Nil创建一个不可变的空列表
scala> val a = Nil a: scala.collection.immutable.Nil.type = List()
例:使用::
方法创建列表,包含-2、-1两个元素
scala> val a = -2 :: -1 :: Nil a: List[Int] = List(-2, -1)
修改
将L(2) 替换成100
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iJSCMo2i-97)(scala.assets/image-.png)]
删除
删除前5个数据 L(5)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8yKEQt1C-98)(scala.assets/image-.png)]
foreach()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ne3EDIS6-98)(scala.assets/image-.png)]
可变列表
//可变列表就是列表的元素、长度都是可变的。 //要使用可变列表,先要导入 import scala.collection.mutable.ListBuffer //可变集合都在`mutable`包中 //不可变集合都在`immutable`包中(默认导入)
定义语法
//使用ListBuffer[元素类型]()创建空的可变列表,语法结构: val/var 变量名 = ListBuffer[Int]() //使用ListBuffer(元素1, 元素2, 元素3...)创建可变列表,语法结构: val/var 变量名 = ListBuffer(元素1,元素2,元素3...)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ScPkGe9-99)(scala.assets/image-.png)]
获取元素(使用括号访问(索引值)
)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qVAMuAAp-99)(scala.assets/image-.png)]
添加元素(+=
)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sUPqjn17-99)(scala.assets/image-.png)]
追加一个列表(++=
)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MXbURv9O-00)(scala.assets/image-022146.png)]
删除元素(-=
)
从左边起,删除第一个 特定元素
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IQVH3g5A-08)(scala.assets/image-057127.png)]
更改元素(使用括号获取元素,然后进行赋值
)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V3pe10Oa-09)(scala.assets/image-.png)]
转换为List(toList
)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cCqK1zEY-09)(scala.assets/image-.png)]
转换为Array(toArray
)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S6Q1ophd-09)(scala.assets/image-.png)]
列表常用操作
以下是列表常用的操作: - 判断列表是否为空(isEmpty) - 拼接两个列表(++) - 获取列表的首个元素(head)和剩余部分(tail) - 反转列表(reverse) - 获取前缀(take)、获取后缀(drop) - 扁平化(flaten) - 拉链(zip)和拉开(unzip) - 转换字符串(toString) - 生成字符串(mkString) - 并集(union)去重(distinct) - 交集(intersect) - 差集(diff)
判断列表是否为空(isEmpty)
scala> val a = List(1,2,3,4) a: List[Int] = List(1, 2, 3, 4) scala> a.isEmpty res51: Boolean = false
拼接两个列表(++)
scala> val a = List(1,2,3) a: List[Int] = List(1, 2, 3) scala> val b = List(4,5,6) b: List[Int] = List(4, 5, 6) scala> a ++ b res52: List[Int] = List(1, 2, 3, 4, 5, 6)
前面的类型为主
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SUHZpedu-10)(scala.assets/image-.png)]
获取列表的首个元素(head)和剩余部分(tail)
scala> val a = List(1,2,3) a: List[Int] = List(1, 2, 3) scala> a.head res4: Int = 1 scala> a.tail res5: List[Int] = List(2, 3)
反转列表(reverse)
scala> val a = List(1,2,3) a: List[Int] = List(1, 2, 3) scala> a.reverse res6: List[Int] = List(3, 2, 1)
获取前缀(take)、获取后缀(drop)
scala> val a = List(1,2,3,4,5) a: List[Int] = List(1, 2, 3, 4, 5) scala> a.take(3) res56: List[Int] = List(1, 2, 3) scala> a.drop(3) res60: List[Int] = List(4, 5)
扁平化(flaten)
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)
拉链(zip)和拉开(unzip)
scala> val a = List("zhangsan", "lisi", "wangwu") a: List[String] = List(zhangsan, lisi, wangwu) scala> val b = List(19, 20, 21) b: List[Int] = List(19, 20, 21) scala> a.zip(b) res1: List[(String, Int)] = List((zhangsan,19), (lisi,20), (wangwu,21)) scala> res1.unzip res2: (List[String], List[Int]) = (List(zhangsan, lisi, wangwu),List(19, 20, 21))
转换字符串(toString)
scala> val a = List(1,2,3,4) a: List[Int] = List(1, 2, 3, 4) scala> println(a.toString) List(1, 2, 3, 4)
生成字符串(mkString)
scala> val a = List(1,2,3,4) a: List[Int] = List(1, 2, 3, 4) scala> a.mkString res7: String = 1234 scala> a.mkString(":") res8: String = 1:2:3:4
并集(union),去重(distinct)
scala> val a1 = List(1,2,3,4) a1: List[Int] = List(1, 2, 3, 4) scala> val a2 = List(3,4,5,6) a2: List[Int] = List(3, 4, 5, 6) // 并集操作 scala> a1.union(a2) res17: List[Int] = List(1, 2, 3, 4, 3, 4, 5, 6) // 可以调用distinct去重 scala> a1.union(a2).distinct res18: List[Int] = List(1, 2, 3, 4, 5, 6)
交集(intersect)
scala> val a1 = List(1,2,3,4) a1: List[Int] = List(1, 2, 3, 4) scala> val a2 = List(3,4,5,6) a2: List[Int] = List(3, 4, 5, 6) scala> a1.intersect(a2) res19: List[Int] = List(3, 4)
差集(diff)
scala> val a1 = List(1,2,3,4) a1: List[Int] = List(1, 2, 3, 4) scala> val a2 = List(3,4,5,6) a2: List[Int] = List(3, 4, 5, 6) scala> a1.diff(a2) res24: List[Int] = List(1, 2)
找元素的index
list.indexOf(str) //找str在list中的索引,如果没找到则返回-1
数组
定长数组(Array)
* 定长数组指的是数组的 长度 是 不允许改变 的 * 数组的 元素 是 可以改变 的 * 在scala中,数组的泛型使用`[]`来指定 * 使用`()`来获取元素
定义Array
// 通过指定长度定义数组 val/var 变量名 = new Array[元素类型](数组长度) 如:val array = new Array[Int](3) // 用元素直接初始化数组 val/var 变量名 = Array(元素1, 元素2, 元素3...) 如:val array = Array(4,12,6,3,8,9,5)
修改
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5dcFUOsb-74)(scala.assets/image-.png)]
Array排序
sortWith( )
//这种方法数组必须是:Int,Double, Float, Long sortWith(_ < _) 从小到大 sortWith(_ > _) 从大到小
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lBwylalG-76)(scala.assets/image-.png)]
sortBy( )
/*按照某一列排序*/ // 默认从小到大排序 // .reverse表示对列表倒叙. sortBy和reverse配合实验=>从大到小排序
按照第二列排序:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BZz0upJa-76)(scala.assets/image-.png)]
变长数组(ArrayBuffer)
* 变长数组指的是数组的长度是可变的,可以往数组中添加、删除元素 * 创建变长数组,需要提前导入ArrayBuffer类 import scala.collection.mutable.ArrayBuffer
定义Buffer
//创建空的ArrayBuffer变长数组,语法结构: val/var a = ArrayBuffer[元素类型]() // 创建带有初始元素的ArrayBuffer val/var a = ArrayBuffer(元素1,元素2,元素3....)
删除
remove
//从data(i)起,连续删除 j个元素 data.remove(i, j)
例:从B(2)开始连续删除两个数据。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Le5SlTrv-76)(scala.assets/image-.png)]
-=
//从左边起,删除第一个x data -= x
例:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i9FoL03o-77)(scala.assets/image-.png)]
插入
insert
//在data.insert(i)位置插入 x元素 data.insert(i, x)
例:把999插入到B(2)这个位置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fM953TdB-77)(scala.assets/image-.png)]
+=
//在data尾部添加 x (有点python的append的味道) data += x
例:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6kKN5VLP-78)(scala.assets/image-.png)]
合并
++=
//data1 和 data2 可变数组合并 data1 ++= data2
例:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TZLzKkoZ-78)(scala.assets/image-.png)]
数组算法
求和 — sum
scala> val a = Array(1,2,3,4) a: Array[Int] = Array(1, 2, 3, 4) scala> a.sum res49: Int = 10
最大值 — max
scala> val a = Array(4,1,2,4,10) a: Array[Int] = Array(4, 1, 2, 4, 10) scala> a.max res50: Int = 10
最小值 — min
scala> val a = Array(4,1,2,4,10) a: Array[Int] = Array(4, 1, 2, 4, 10) scala> a.min res51: Int = 1
升排序 — sorted
数组反转 — reverse
// 升序排序 scala> a.sorted res53: Array[Int] = Array(1, 2, 4, 4, 10) // 降序 scala> a.sorted.reverse res56: Array[Int] = Array(10, 4, 4, 2, 1)
元组
// 元组可以用来包含一组不同类型的值。例如:姓名,年龄,性别,出生年月。 // 元组的元素是不可变的。
语法
//使用括号来定义元组 val/var 元组 = (元素1, 元素2, 元素3....) //使用箭头来定义元组(元组只有两个元素) val/var 元组 = 元素1->元素2
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y871NuAp-79)(scala.assets/image-.png)]
访问元组
// 使用_1、_2、_3....来访问元组中的元素,_1表示访问第一个元素,依次类推 //注意,不可以用 t(i)来访问哦
例:
scala> val a = "zhangsan" -> "male" a: (String, String) = (zhangsan,male) // 获取第一个元素 scala> a._1 res41: String = zhangsan // 获取第二个元素 scala> a._2 res42: String = male
集合
Set(集)是代表没有重复元素的集合。Set具备以下性质: 1. 元素不重复 2. 不保证插入顺序 scala 中的集也分为两种,一种是不可变集,另一种是可变集。
不可变集
定义语法
//创建一个空的不可变集,语法格式: val/var 变量名 = Set[类型]() //给定元素来创建一个不可变集,语法格式: val/var 变量名 = Set(元素1, 元素2, 元素3...)
例:
//定义一个空的不可变集 scala> val a = Set[Int]() a: scala.collection.immutable.Set[Int] = Set() //定义一个不可变集,保存以下元素:1,1,3,2,4,8 scala> val a = Set(1,1,3,2,4,8) a: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 8, 4)
基本操作
- 获取集的大小(size) - 遍历集(和遍历数组一致) - 添加一个元素,生成一个Set(`+`) - 删除一个元素,生成一个Set(`-`) - 拼接两个集,生成一个Set(++) - 拼接集和列表,生成一个Set(++)
// 创建集,可以看出集合是的元素是单一,无序的。 scala> val a = Set(1,1,2,3,4,5) a: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)
获取集的大小(size)
// 获取集的大小 scala> a.size res0: Int = 5
遍历集(和遍历数组一致)
// 遍历集 scala> for(i <- a) println(i) 5 1 6 2 3 4
添加一个元素,生成一个Set(+
)
//添加一个元素 scala> a + 100 res5: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4, 100)
删除一个元素,生成一个Set(-
)
// 删除一个元素 scala> a - 1 res5: scala.collection.immutable.Set[Int] = Set(5, 2, 3, 4)
拼接两个集,生成一个Set(++)
// 拼接两个集 scala> a ++ Set(6,7,8) res2: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 7, 3, 8, 4)
拼接集和列表,生成一个Set(++)
// 拼接集和列表 scala> a ++ List(6,7,8,9) res6: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 9, 2, 7, 3, 8, 4)
可变集
定义方法
//可变集合不可变集的创建方式一致,只不过需要提前导入一个可变集类。 手动导入: import scala.collection.mutable.Set
例:
import scala.collection.mutable.Set scala> val a = Set(1,2,3,4) a: scala.collection.mutable.Set[Int] = Set(1, 2, 3, 4)
操作方法
添加元素(+=)
scala> b res28: scala.collection.mutable.Set[Int] = Set(1, 2, 3, 4) scala> b += 111 res29: b.type = Set(1, 2, 3, 111, 4)
删除元素(-=)
scala> b res31: scala.collection.mutable.Set[Int] = Set(1, 3, 111, 4) scala> b -= 3 res32: b.type = Set(1, 111, 4)
映射(Map)— 字典
//Map可以称之为映射。它是由键值对组成的集合。在scala中,Map也分为不可变Map和可变Map。 //Map 不就是他妈Python上的字典吗。包括玩法都差不多 * 查 : map(旧键) * 曾 : map(新键) = 值 * 改 : map(旧键) = 值
不可变Map
定义语法
val/var map = Map(键->值, 键->值, 键->值...) // 推荐,可读性更好 val/var map = Map((键, 值), (键, 值), (键, 值), (键, 值)...)
例:定义一个映射,包含以下学生姓名和年龄数据。 获取zhangsan的年龄
scala> val map = Map("zhangsan"->30, "lisi"->40) map: scala.collection.immutable.Map[String,Int] = Map(zhangsan -> 30, lisi -> 40) //或: scala> val map = Map(("zhangsan", 30), ("lisi", 30)) map: scala.collection.immutable.Map[String,Int] = Map(zhangsan -> 30, lisi -> 30) // 根据key获取value scala> map("zhangsan") res10: Int = 30
可变Map
定义语法
// 定义语法与不可变Map一致。但定义可变Map需要手动导入 import scala.collection.mutable.Map
例:定义一个映射,包含以下学生姓名和年龄数据。 修改“zhangsan”的年龄为20
import scala.collection.mutable.Map scala> val map = Map("zhangsan"->30, "lisi"->40) map: scala.collection.mutable.Map[String,Int] = Map(lisi -> 40, zhangsan -> 30) // 修改value scala> map("zhangsan") = 20 //添加一个值 scala> map("wangwu") = 36 scala> map res44: scala.collection.mutable.Map[String,Int] = Map(lisi -> 40, zhangsan -> 66, wangwu -> 36)
Map基本操作
//Map操作 跟Python字典的玩法真的是一模一样。 - 获取值(`map(key)`) - 获取所有key(`map.keys`) - 获取所有value(`map.values`) - 遍历map集合 - getOrElse - 增加key,value对 - 删除key
准备数据,不可变Map, 可变Map
scala> val map_NoChange = Map("zhangsan"->30, "lisi"->40) map_NoChange: scala.collection.immutable.Map[String,Int] = Map(zhangsan -> 30, lisi -> 40) scala> import scala.collection.mutable.Map import scala.collection.mutable.Map scala> val map_Change = Map("zhangsan"->30, "lisi"->40) map_Change: scala.collection.mutable.Map[String,Int] = Map(lisi -> 40, zhangsan -> 30)
获取值(map(key)
)
// 获取zhagnsan的年龄 scala> map_NoChange("zhangsan") res0: Int = 30 scala> map_Change("zhangsan") res1: Int = 30
获取所有key(map.keys
)
// 获取所有的学生姓名 scala> map_NoChange.keys res2: Iterable[String] = Set(zhangsan, lisi) scala> map_Change.keys res3: Iterable[String] = Set(lisi, zhangsan)
获取所有value(map.values
)
// 获取所有的学生年龄 scala> map_NoChange.values res4: Iterable[Int] = MapLike.DefaultValuesIterable(30, 40) scala> map_Change.values res5: Iterable[Int] = HashMap(40, 30)
遍历map集合
// 打印所有的学生姓名和年龄 scala> for((x,y) <- map_NoChange) println(s"$x $y") zhangsan 30 lisi 40 scala> for((x,y) <- map_Change) println(s"$x $y") lisi 40 zhangsan 30
查询,若不存在返回x ( getOrElse(键, x) )
// 获取wangwu的年龄,如果wangwu不存在,则返回-1 scala> map_NoChange.getOrElse("wangwu", -1) res8: Int = -1 scala> map_Change.getOrElse("wangwu", -1) res9: Int = -1
增加key,value对
// 新增一个学生:wangwu, 35 scala> map_NoChange + "wangwu"->36 res10: (String, Int) = (Map(zhangsan -> 30, lisi -> 40)wangwu,36) scala> map_Change + "wangwu"->36 res11: (String, Int) = (Map(lisi -> 40, zhangsan -> 30)wangwu,36) //上面这样写,好像错了: 上面这样就变成了: (map+"wangwu") -> 36 。 因为 -> 的优先级大于 + 结果就变成了一个 (String -> Int)的元组。 注意如下: 结果._1 = Map(lisi -> 40, zhangsan -> 30)wangwu 这是个字符串,非表达式 结果._2 = 36 这是个Int //上面好像这么写是错的,写成下面这样就好了 scala> map_Change + ("wangwu"->36) res16: scala.collection.mutable.Map[String,Int] = Map(lisi -> 40, zhangsan -> 30, wangwu -> 36) scala> map_NoChange + ("wangwu"->36) res17: scala.collection.immutable.Map[String,Int] = Map(zhangsan -> 30, lisi -> 40, wangwu -> 36)
删除key
// 将lisi从可变映射中移除 scala> map_NoChange - "lisi" res14: scala.collection.immutable.Map[String,Int] = Map(zhangsan -> 30) scala> map_Change - "lisi" res15: scala.collection.mutable.Map[String,Int] = Map(zhangsan -> 30)
切片(slice)
//使用和python一样,但是写法不一样。 //scala的切片用slice
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-50h1rQdC-79)(scala.assets/image-.png)]
迭代器(iterator)
// scala针对每一类集合都提供了一个迭代器(iterator),用来迭代访问集合。
使用迭代器遍历集合
* 使用`iterator`方法可以从集合获取一个迭代器 * 迭代器的两个基本操作 * hasNext——查询容器中是否有下一个元素 * next——返回迭代器的下一个元素,如果没有,抛出NoSuchElementException * 每一个迭代器都是有状态的 * 迭代完后保留在最后一个元素的位置 * 再次使用则抛出NoSuchElementException * 可以使用while或者for来逐个返回元素
例:定义一个列表,包含以下元素:1,2,3,4,5。 使用while循环和迭代器,遍历打印该列表
scala> val a = List(1,2,3,4,5) a: List[Int] = List(1, 2, 3, 4, 5) scala> val ite = a.iterator ite: Iterator[Int] = non-empty iterator scala> while(ite.hasNext){
| println(ite.next) | } 1 2 3 4 5 scala>
用for 便利迭代器
scala> val a = List(1,2,3,4,5) a: List[Int] = List(1, 2, 3, 4, 5) scala> a res0: List[Int] = List(1, 2, 3, 4, 5) scala> val ite = a.iterator ite: Iterator[Int] = non-empty iterator scala> for (i <- ite)println(i) 1 2 3 4 5 scala>
函数式编程
//我们将来使用Spark/Flink的大量业务代码都会使用到函数式编程。下面的这些操作是学习的重点。 - 遍历(`foreach`) - 映射(`map`) - 映射扁平化(`flatmap`) - 过滤(`filter`) - 是否存在(`exists`) - 排序(`sorted`、`sortBy`、`sortWith`) - 分组(`groupBy`) - 聚合计算(`reduce`) - 折叠(`fold`)
遍历(foreach)
//之前,学习过了使用for表达式来遍历集合。我们接下来将学习scala的函数式编程,使用`foreach`方法来进行遍历、迭代。它可以让代码更加简洁。 //注意,foreach是没有返回值的哦。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aimQskku-61)(scala.assets/image-.png)]
foreach执行过程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GScfMzdY-63)(scala.assets/image-.png)]
例:有一个列表,包含以下元素1,2,3,4,请使用foreach方法遍历打印每个元素
// 定义一个列表 scala> val a = List(1,2,3,4) a: List[Int] = List(1, 2, 3, 4) // 迭代打印 scala> a.foreach((x:Int)=>println(x))
使用类型推断简化函数定义:
/* 上述案例函数定义有点啰嗦,我们有更简洁的写法。因为使用foreach去迭代列表,而列表中的每个元素类型是确定的 * scala可以自动来推断出来集合中每个元素参数的类型 * 创建函数时,可以省略其参数列表的类型 */ scala> val a = List(1,2,3,4) a: List[Int] = List(1, 2, 3, 4) // 省略参数类型 scala> a.foreach((x)=>println(x)) // 如果只有一个参数,那么:括号都可以省略。 scala> a.foreach(x=>println(x))
使用下划线来简化函数定义:
/* 当函数参数,只在函数体中出现一次,而且函数体没有嵌套调用时,可以使用下划线来简化函数定义 */ scala> val a = List(1,2,3,4) a: List[Int] = List(1, 2, 3, 4) scala> a.foreach(println(_)) //函数的参数x 只在函数体中出现一次,才用_ //* 如果方法参数是函数,如果出现了下划线,scala编译器会自动将代码封装到一个函数中参数列表也是由scala编译器自动处理
映射(map)
//和python上的map玩法一样的。 //集合的映射操作是将来在编写Spark/Flink用得最多的操作,是我们必须要掌握的。因为进行数据计算的时候,就是一个将一种数据类型转换为另外一种数据类型的过程。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KEi0yDb2-63)(scala.assets/image-.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7O8fdESs-64)(scala.assets/image-.png)]
例: 对List中的每一个元素加1
scala> val a = List(1,2,3,4) a: List[Int] = List(1, 2, 3, 4) //写法1 scala> a.map(x=>x+1) res4: List[Int] = List(2, 3, 4, 5) //写法2 scala> a.map(_ + 1) res4: List[Int] = List(2, 3, 4, 5) //写法3: 直接调用函数, 和方法1, 2 本质都是一样的。 scala> val add = (x:Int, y:Int) => x + y add: (Int, Int) => Int = $$Lambda$1142/@7d83321a scala> val x = a.map(add(_,1)) x: List[Int] = List(2, 3, 4, 5)
映射扁平化(flatmap)
// 可以把flatMap,理解为先map,然后再flatten - map是将列表中的元素转换为一个List - flatten再将整个列表进行扁平化
例:有一个包含了若干个文本行的列表:“hadoop hive spark flink flume”, “kudu hbase sqoop storm” 。 获取到文本行中的每一个单词,并将每一个单词都放到列表中。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JvqFwWw9-64)(scala.assets/image-.png)]
scala> val a = List("hadoop hive spark flink flume","kudu hbase sqoop storm") a: List[String] = List(hadoop hive spark flink flume, kudu hbase sqoop storm) // map + flatten 做法 scala> a.map(_.split(" ")) res20: List[Array[String]] = List(Array(hadoop, hive, spark, flink, flume), Array(kudu, hbase, sqoop, storm)) scala> a.map(_.split(" ")).flatten res21: List[String] = List(hadoop, hive, spark, flink, flume, kudu, hbase, sqoop, storm) // flatMap 做法 scala> a.flatMap(x => x.split(" ")) res24: List[String] = List(hadoop, hive, spark, flink, flume, kudu, hbase, sqoop, storm)
过滤(filter)
// 过滤符合一定条件的元素
例:1–10中,过滤出所以偶数
scala> val a = (1.to(10)).toList a: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) scala> a.filter(_ % 2 == 0) res28: List[Int] = List(2, 4, 6, 8, 10)
是否存在(exists)
排序(sorted、sortBy、sortWith)
// 在scala集合中,可以使用以下几种方式来进行排序 * sorted默认排序 * sortBy指定字段排序 * sortWith自定义排序
sorted默认排序
scala> List(3,1,2,9,7).sorted res16: List[Int] = List(1, 2, 3, 7, 9)
sortBy指定字段排序
//根据传入的函数转换后,再进行排序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZHo938Jb-65)(scala.assets/image-.png)]
//实验1: 注意要看明白,是神马情况 scala> val a = List("01 hadoop", "02 flume", "03 hive", "04 spark") a: List[String] = List(01 hadoop, 02 flume, 03 hive, 04 spark) scala> a.sortBy(_.split(" ")(1)) res30: List[String] = List(02 flume, 01 hadoop, 03 hive, 04 spark) scala> a.sortBy(_.split(" ")(0)) res31: List[String] = List(01 hadoop, 02 flume, 03 hive, 04 spark) //实验2: scala> b res43: List[(String, Int)] = List((zhangsan,19), (lisi,55), (wangwu,22)) scala> b.sortBy(_._1) res47: List[(String, Int)] = List((lisi,55), (wangwu,22), (zhangsan,19)) scala> b.sortBy(_._2) res48: List[(String, Int)] = List((zhangsan,19), (wangwu,22), (lisi,55))
sortWith自定义排序
//自定义排序,根据一个函数来进行自定义排序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c2JuleVi-65)(scala.assets/image-.png)]
scala> val a = List(2,3,1,6,4,5) a: List[Int] = List(2, 3, 1, 6, 4, 5) scala> a.sortWith((x,y) => if(x<y)true else false) res15: List[Int] = List(1, 2, 3, 4, 5, 6) scala> res15.reverse res18: List[Int] = List(6, 5, 4, 3, 2, 1) /*使用下划线简写上述案例*/ // 函数参数只在函数中出现一次,可以使用下划线代替 scala> a.sortWith(_ < _).reverse res19: List[Int] = List(6, 5, 4, 3, 2, 1)
分组(groupBy)
我们如果要将数据按照分组来进行统计分析,就需要使用到分组方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MBDp51Vs-66)(scala.assets/image-.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sLffQJkY-66)(scala.assets/image-.png)]
/* 《总结 : groupBy 对数据进行分组》 1. 返回值为一个字典(Map) Map(key1 -> List(key1组数据完整值), key2 -> List(key2组数据完整值)) 例如: List("张三"->"男", "李四"->"女", "王五"->"男") .a.groupBy(_._2) 得到:Map(男 -> List((张三,男), (王五,男)), 女 -> List((李四,女))) */
例:对同学按照性别进行分组
scala> val a = List("张三"->"男", "李四"->"女", "王五"->"男") a: List[(String, String)] = List((张三,男), (李四,女), (王五,男)) // 按照性别分组 scala> a.groupBy(_._2) res0: scala.collection.immutable.Map[String,List[(String, String)]] = Map(男 -> List((张三,男), (王五,男)), 女 -> List((李四,女))) // 将分组后的映射转换为性别/人数元组列表 scala> res0.map(x => x._1 -> x._2.size) res3: scala.collection.immutable.Map[String,Int] = Map(男 -> 2, 女 -> 1)
聚合计算(reduce)
//聚合操作,可以将一个列表中的数据合并为一个。这种操作经常用来统计分析中 //reduce表示将列表,传入一个函数进行聚合计算 /* reduce和reduceLeft效果一致,表示从左到右计算 reduceRight表示从右到左计算 */
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Do8H3RnF-67)(scala.assets/image-.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MS1YTuhc-67)(scala.assets/image-.png)]
例:求和
scala> val a = List(1,2,3,4,5,6,7,8,9,10) a: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) scala> a.reduce((x,y) => x + y) res5: Int = 55 // 第一个下划线表示第一个参数,就是历史的聚合数据结果 // 第二个下划线表示第二个参数,就是当前要聚合的数据元素 scala> a.reduce(_ + _) res53: Int = 55 // 与reduce一样,从左往右计算 scala> a.reduceLeft(_ + _) res0: Int = 55 // 从右往左聚合计算 scala> a.reduceRight(_ + _) res1: Int = 55
折叠(fold)
//fold与reduce很像,但是多了一个指定初始值参数 /* fold和foldLet效果一致,表示从左往右计算 foldRight表示从右往左计算 */
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nvdw5HFK-68)(scala.assets/image-.png)]
例:定义一个列表,包含以下元素:1,2,3,4,5,6,7,8,9,10 使用fold方法计算所有元素的和。
scala> val a = List(1,2,3,4,5,6,7,8,9,10) a: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) scala> a.fold(0)(_ + _) res4: Int = 155
至此关于scala的初级入门学习已经完毕。
到此这篇scala编程初级实践_scala3的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/scalabc/1832.html