当前位置:网站首页 > Scala编程 > 正文

scala编程初级实践_scala3

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的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • Scala基础入门:从零开始学习Scala编程2024-11-16 13:09:08
  • scala编程实战 pdf_scala一般做什么开发2024-11-16 13:09:08
  • 每当我想放弃Scala,我就写写Python和Java_为什么不建议学python2024-11-16 13:09:08
  • scala 函数_编程2024-11-16 13:09:08
  • scala function_编程2024-11-16 13:09:08
  • scala编程第4版_scala菜鸟教程2024-11-16 13:09:08
  • scala matches_scratch算法2024-11-16 13:09:08
  • scala编程实战 pdf_人工智能语言python2024-11-16 13:09:08
  • Java-Scala编程规范超精简2024-11-16 13:09:08
  • scala编程实战 pdf_scratch2.0编程2024-11-16 13:09:08
  • 全屏图片