scala编程(初级)

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-1658546372321)(scala.assets/image-20211027213633410.png)]

scala程序是如何编译,执行的?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IHPPUNlx-1658546372323)(scala.assets/image-20211027213836372.png)]

// java编译器和scala编译器不通用哦.

// scala也有自己的类库, scala也可以使用java类库哦.

// scala

基础

交互式,文件式例子

交互式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-grLBWoIS-1658546372323)(scala.assets/image-20210830133231577.png)]

文件式

//HelloWorld.scala 代码如下:

object HelloWorld {
   /* 这是我的第一个 Scala 程序
    * 以下程序将输出'Hello World!' 
    */
   def main(args: Array[String]) {
      println("Hello, world!") // 输出 Hello World
   }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2dgHhZh3-1658546372324)(scala.assets/image-20210830133434401.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-1658546372324)(scala.assets/image-20211028100331149.png)]

数据类型

//scala中有着与java相同的数据类型。 如下说说与之不同的地方:
	scala中所有的类型都使用大写字母开头。
	整形使用Int,而不是Integer
	scala 申请变量的时候可以不写类型,让scala编译器自己推断去吧。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tpEVg3jR-1658546372325)(scala.assets/image-20210830135413572.png)]

Scala类型层次结构
//Scala的数据类型也是“单根继承”体系, 都是继承Any这个类型

//AnyVal 是所有“值类型”的父类。
//AnyRef 是所有“引用类型”的父类

//Unit 表示“空类型”
	他只有一个实例() 。它类似于java中的void, 但是scala比java更加的面向对象。

//Null 所有“引用类型”的子类。
	也就是Nul类型可以赋值给所有“引用类型”

//Nothing 所有类型的子类。 
	Nothing 表示方法抛出异常的时候,返回的子类。。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qauj3vwv-1658546372325)(scala.assets/image-20211028104338861.png)]

Null 类型是不可以赋值给 AnyVal 下面的类型的, 只可以赋值给AnyRef下的类型。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tJBvySMO-1658546372326)(scala.assets/image-20211028110559816.png)]

运算符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aCzNU0pw-1658546372326)(scala.assets/image-20211028103114605.png)]

条件表达式(if)

//if 的使用,语法和java一样。在此不多bb。 下面主要说和java不一样的地方:
	Scala中if是有返回值的。
	Scala中没有三元表达式,可以使用if表达式代替 三元表达式
有返回值的if

例:当sex 是 “male”就返回1 , 否则就返回0

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2gq23e7w-1658546372327)(scala.assets/image-20211028113904773.png)]

块表达式
//scala中使用{} 表示块表达式if表示式一样,块表达式也是有值的。值就是最后一个表达式的值。

// 块表达式是很牛逼的一个东西。这玩意用的好,代码就精巧。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O0yxjpK9-1658546372327)(scala.assets/image-20211028115157383.png)]

循环

for

遍历循环1到9

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PStir5sz-1658546372328)(scala.assets/image-20211028150220215.png)]

在scala中,数字也是一个对象,也可以调用 .to方法。

//scala中 x.to(y)  相当于 python 中 range(x, y+1)

// 1.to(10)  也可以写成  1 to 10

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3CUMIEne-1658546372328)(scala.assets/image-20211028150629317.png)]

for嵌套循环

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8AR7aK0Q-1658546372329)(scala.assets/image-20211028152304039.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-1658546372329)(scala.assets/image-20211028154508520.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-1658546399390)(scala.assets/image-20211028161335519.png)]

标准写法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bB9fBOOr-1658546399391)(scala.assets/image-20211028162119791.png)]

返回值推断
//scala定义方法可以省略返回值,由scala自动推断返回值类型。这样方法定义后更加简洁。 
//定义递归方法,不能省略返回值类型
//return 什么时候都可以不写,看你心情。

例:定义递归方法(求阶乘)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R2mn2JxF-1658546399392)(scala.assets/image-20211028162618915.png)]

方法的参数
scala中的方法参数,使用比较灵活。它支持以下几种类型的参数:
    - 默认参数 (和py一样)
    - 带名参数 (和py一样)
    - 变长参数 ( *

1.默认参数:在定义方法时可以给参数定义一个默认值。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AXUIZ0qW-1658546399392)(scala.assets/image-20211028163213593.png)]

2.带名参数:在调用方法时,可以指定参数的名称来进行调用。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CecpdFQc-1658546399393)(scala.assets/image-20211028163303876.png)]

3.边长参数:如果方法的参数是不固定的,可以定义一个方法的参数是变长参数。

语法格式:

def 方法名(参数名:参数类型*):返回值类型 = {
    方法体
}

//在参数类型后面加一个`*`号,表示参数可以是0个或者多个

**例子:**定义一个计算若干个值相加的方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5rmKjRe2-1658546399394)(scala.assets/image-20211028164018151.png)]

输出:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j12uuZkv-1658546399394)(scala.assets/image-20211028164038011.png)]

疑问:不定长参数的类型式什么?猜想是数组。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2SNdvULt-1658546399395)(scala.assets/image-20211028164145483.png)]

输出:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YWdxewcX-1658546399395)(scala.assets/image-20211028164204031.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-1658546399396)(scala.assets/image-20211029113909816.png)]

4.无符号调用法

//如果方法没有参数,可以省略方法名后面的括号

def m3()=println("hello")
m3

5.操作符也是方法

在scala中:
	所有的操作符都是方法
	操作符是一个方法名字是符号的方法.

1 + 1 这个表达式实际上也是一个方法调用哦。scala的特别之处,嘻嘻。

//下面不写不知道,一写么的吓一跳。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-70lgbz2i-1658546399396)(scala.assets/image-20211029113709782.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/256869439@7b5833ee

scala> add1
res14: (Int, Int) => Int = $$Lambda$1092/256869439@7b5833ee

scala> add1(1,1)
res15: Int = 2

scala> val a1 = add1
a1: (Int, Int) => Int = $$Lambda$1092/256869439@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 数组中
13byte[] 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 得到的
30String 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-1658546399397)(scala.assets/image-20211027170608831.png)]

删除

删除前5个数据 L(5)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8yKEQt1C-1658546399398)(scala.assets/image-20211027170859736.png)]

foreach()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ne3EDIS6-1658546399398)(scala.assets/image-20211027171140054.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-1658546399399)(scala.assets/image-20211029175647356.png)]

获取元素(使用括号访问(索引值)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qVAMuAAp-1658546399399)(scala.assets/image-20211029175846690.png)]

添加元素(+=

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sUPqjn17-1658546399399)(scala.assets/image-20211029175938568.png)]

追加一个列表(++=

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MXbURv9O-1658546399400)(scala.assets/image-20211029180022146.png)]

删除元素(-=

从左边起,删除第一个 特定元素

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IQVH3g5A-1658546399408)(scala.assets/image-20211029180057127.png)]

更改元素(使用括号获取元素,然后进行赋值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V3pe10Oa-1658546399409)(scala.assets/image-20211029180143001.png)]

转换为List(toList

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cCqK1zEY-1658546399409)(scala.assets/image-20211029180230402.png)]

转换为Array(toArray

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S6Q1ophd-1658546399409)(scala.assets/image-20211029180257150.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-1658546399410)(scala.assets/image-20211029182153619.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-1658546420774)(scala.assets/image-20211027172854141.png)]

Array排序
sortWith( )
//这种方法数组必须是:Int,Double, Float, Long

sortWith(_ < _)	 从小到大
sortWith(_ > _)  从大到小

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lBwylalG-1658546420776)(scala.assets/image-20211027173107454.png)]

sortBy( )
/*按照某一列排序*/

// 默认从小到大排序
// .reverse表示对列表倒叙.  sortBy和reverse配合实验=>从大到小排序

按照第二列排序:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BZz0upJa-1658546420776)(scala.assets/image-20211027173851618.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-1658546420776)(scala.assets/image-20211027172342182.png)]

-=
//从左边起,删除第一个x
data -= x

例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i9FoL03o-1658546420777)(scala.assets/image-20211029165402269.png)]

插入
insert
//在data.insert(i)位置插入 x元素
data.insert(i, x)

**例:**把999插入到B(2)这个位置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fM953TdB-1658546420777)(scala.assets/image-20211027172442825.png)]

+=
//在data尾部添加 x	(有点python的append的味道)
data += x

例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6kKN5VLP-1658546420778)(scala.assets/image-20211029165639538.png)]

合并
++=
//data1 和 data2 可变数组合并
data1 ++= data2

例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TZLzKkoZ-1658546420778)(scala.assets/image-20211029165921471.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-1658546420779)(scala.assets/image-20211029172436615.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-1658546420779)(scala.assets/image-20211124092843158.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-1658546449761)(scala.assets/image-20211030111532441.png)]

foreach执行过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GScfMzdY-1658546449763)(scala.assets/image-20211030111623440.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-1658546449763)(scala.assets/image-20211030114318070.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7O8fdESs-1658546449764)(scala.assets/image-20211030114357908.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/1505791581@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-1658546449764)(scala.assets/image-20211030115625456.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-1658546449765)(scala.assets/image-20211030121406153.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-1658546449765)(scala.assets/image-20211030121440557.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-1658546449766)(scala.assets/image-20211030122607884.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sLffQJkY-1658546449766)(scala.assets/image-20211030122630438.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-1658546449767)(scala.assets/image-20211030123524634.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MS1YTuhc-1658546449767)(scala.assets/image-20211030123542043.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-1658546449768)(scala.assets/image-20211030123736570.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的初级入门学习已经完毕。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值