當前位置:網站首頁>scala編程(初級)

scala編程(初級)

2022-07-23 21:07:41大寧哥

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的初級入門學習已經完畢。

版權聲明
本文為[大寧哥]所創,轉載請帶上原文鏈接,感謝
https://cht.chowdera.com/2022/204/202207232106554040.html

隨機推薦