1. 程式人生 > >scala的面向對象,繼承與特質

scala的面向對象,繼承與特質

所有 ostream take 太差 sel clas otf 返回結果 rtb


---------------------------------------------------------------------------------------
1、scala編程語言

2、Spark Core : Spark內核 ,最重要的一個部分。
3、Spark SQL : 類似於 hive 和 pig。數據分析引擎。sql語句提交到spark集群中運行。
4、Spark Streaming :類似於 storm,用於流式計算、實時計算。本質:一個離線計算。

------------------------------Scala編程語言---------------------------------------------

---------------Scala基礎--------------------------
一、scala簡介
1、scala是一個多範式的編程語言(支持多種方式的編程)
(1)使用面向對象編程:封裝、繼承、多態
(2)使用函數式編程:最大的特定
(*)優點:代碼非常簡潔
(*)缺點:可讀性太差,尤其是隱式類、隱式函數、隱式參數

2、安裝和配置scala
(*)基於JDK,先安裝JDK
(*)scala:2.11.8(spark 2.1.0)
(*)配置環境變量:SCALA_HOME
(*)%SCALA_HOME%\bin 配置到path中

下載地址:https://www.scala-lang.org

文檔地址:https://www.scala-lang.org/api/2.11.8/#scala.math.package

(*)開發環境
(1)REPL命令行
(2)IDEA : 需要安裝scala插件。

二、Scala中的數據類型和變量常量

1、註意一點:scala中所有的數據,都是對象。
舉例:1 java int 。在scala中,1 就是一個對象。

2、基本數據類型
Byte 8位有符號數字
Short 16位有符號數字
Int ...
Long
Float
Double

字符串類型
String
字符
Char

scala中字符串的插值操作:就是相當於字符串的拼接
scala> var s1 : String = "Hello "
s1: String = "Hello "

scala> "My name is Tom and ${s1}"
res1: String = My name is Tom and ${s1}

插值操作時,需要加入 s
scala> s"My name is Tom and ${s1}"
res2: String = "My name is Tom and Hello "

3、變量var和常量val

scala> val s2 :String = "Hello all"
s2: String = Hello all

scala> s2 = "Hello everyone"
<console>:12: error: reassignment to val
s2 = "Hello everyone"

4、Unit類型和Nothing類型

(1)Unit類型,就是java中的void,沒有返回值

scala> val f = ()
f: Unit = ()

返回值 Unit類型
() 代表了一個函數,這個函數沒有返回值

(2)Nothing類型,在執行過程中,產生了異常Exception

舉例:
scala函數:scala中函數非常重要,是scala的頭等公民
用法很多:函數式編程、高階函數

def myFunction = 函數的實現

scala> def myFun = throw new Exception("Some Error")
myFun: Nothing

三、函數:頭等公民

(一)scala內置函數,可以直接使用的函數

scala> max(1,2)
<console>:12: error: not found: value max
max(1,2)
^

scala> import scala.math
final package math

scala> import scala.math._
import scala.math._

_ 就相當於java中的 * 代表包內所有東西

scala> max(1,2)
res4: Int = 2

res4: Int = 2
定義了一個變量 res4 ,接收了 max 函數的返回值。scala中支持類型的推導。
res4 = ""

(二) 自定義函數
語法:

def 函數名稱([參數名稱:參數類型]*) : 返回值類型 = {
函數的實現
}

舉例:
1、求和
scala> def sum(x:Int,y:Int):Int = x + y
sum: (x: Int, y: Int)Int

scala> sum(1,2)
res5: Int = 3

2、求階乘,5!= 5 * 4* 3 *2* 1
遞歸
scala> def myFactor(x:Int):Int = {
| if(x<=1)
| 1
| else
| x*myFactor(x-1)
| }
myFactor: (x: Int)Int

scala> myFactor(5)
res6: Int = 120

註意:沒有return語句。
函數的最後一句話,就是函數的返回值。

3、求輸入的年份是否是閏年

閏年:
普通閏年:可以被4整除但是不能被100整除的年份
世紀閏年:可以被400整除的年份

scala> def isLeapYear(x:Int) = {
| if(( x%4 == 0 && x%100 != 0) || (x%400==0)) true
| else false
| }
isLeapYear: (x: Int)Boolean

scala> isLeapYear(2019)
res7: Boolean = false

scala> isLeapYear(2008)
res8: Boolean = true

1、( x%4 == 0 && x%100 != 0) || (x%400==0)
2、函數定義的時候,可以不寫返回值,因為scala支持類型推導

四、循環語句
1、類似於java的用法 while dowhile for
2、foreach循環(Spark算子)

講義在代碼中

五、scala的函數參數

1、函數參數的求值策略
(1)call by value :

對函數的實參求值,並且只求一次

(2)call by name : =>

函數實參在函數體內部用到的時候,才會被求值

舉例:

scala> def test1(x:Int,y:Int) = x + x
test1: (x: Int, y: Int)Int

scala> test1(3+4,8)
res9: Int = 14

scala> def test2(x : => Int,y : => Int) = x+x
test2: (x: => Int, y: => Int)Int

scala> test2(3+4,8)
res10: Int = 14

執行過程對比:
test1 ---> test1(3+4,8) ---> test1(7,8) ---> 7+7 ---> 14
test2 ---> test2(3+4,8) ---> (3+4) + (3+4) ---> 14

(3)復雜的例子

def bar(x:Int,y : => Int) : Int = 1
x 是 value y 是 name

定義一個死循環:
def loop() : Int = loop

調用bar函數的時候:
1、bar(1,loop)
2、bar(loop,1)

哪個方式會產生死循環?

scala> def bar(x:Int,y : => Int) : Int = 1
bar: (x: Int, y: => Int)Int

scala> def loop() : Int = loop
loop: ()Int

scala> bar(1,loop)
res11: Int = 1

scala> bar(loop,1)

解析:
1、雖然 y 是 name, 每次調用的時候會被求值。但是,函數體內,沒有調用到y.
2、x 是 value,對函數參數求值,並且只求一次。雖然後面沒有用到x,但求值時產生了死循環。

2、scala中函數參數的類型
(1)默認參數
當你沒有給參數值賦值的時候,就會使用默認值。

def fun1(name:String="Tom") :String = "Hello " + name


scala> def fun1(name:String="Tom") :String = "Hello " + name
fun1: (name: String)String

scala> fun1("Andy")
res0: String = Hello Andy

scala> fun1()
res1: String = Hello Tom


(2)代名參數
當有多個默認參數的時候,通過代名參數可以確定給哪個函數參數賦值。
def fun2(str:String = "Hello " , name:String = " Tom " ,age:Int = 20) = str + name + " age is " +age


scala> def fun2(str:String = "Hello " , name:String = " Tom " ,age:Int = 20) = str + name + " age is " +age
fun2: (str: String, name: String, age: Int)String

scala> fun2()
res2: String = Hello Tom age is 20

scala> fun2("Andy")
res3: String = Andy Tom age is 20

scala> fun2(name="Andy")
res4: String = Hello Andy age is 20


(3)可變參數
類似於java中的可變參數,即 參數數量不固定。
scala> def sum(args:Int*)= {
| var result = 0
| for(s<-args) result +=s
| result
| }
sum: (args: Int*)Int

scala> sum(1,2,3,4)
res5: Int = 10

scala> sum(1,2,3,4,3,4)
res6: Int = 17

六、懶值(lazy)

鋪墊:Spark的核心是 RDD(數據集合),操作數據集合的數據,使用算子來操作RDD(函數、方法)
算子:
Transformation : 延時加載,不會觸發計算
Action : 會立刻觸發計算。

定義:常量如果是lazy的,他的初始化會被延遲,推遲到第一次使用該常量的時候。

舉例:
scala> var x : Int = 10
x: Int = 10

scala> val y : Int = x+1
y: Int = 11

y 的值是x+1 定義後會立即進行計算

scala> lazy val z : Int = x+1
z: Int = <lazy>

z的初始化會被延遲

scala> z
res0: Int = 11

當我們第一次使用z的時候,才會觸發計算

讀文件:
scala> val words = scala.io.Source.fromFile("H:\\tmp_files\\student.txt").mkString
words: String =
1 Tom 12
2 Mary 13
3 Lily 15

scala> lazy val words = scala.io.Source.fromFile("H:\\tmp_files\\student.txt").mkString
words: String = <lazy>

scala> words
res1: String =
1 Tom 12
2 Mary 13
3 Lily 15

scala> lazy val words = scala.io.Source.fromFile("H:\\tmp_files\\student123123121.txt").mkString
words: String = <lazy>

定義成lazy後,初始化被延遲,所以不會拋異常

scala> val words = scala.io.Source.fromFile("H:\\tmp_files\\student123123121.txt").mkString
java.io.FileNotFoundException: H:\tmp_files\student123123121.txt (系統找不到指定的文件。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at scala.io.Source$.fromFile(Source.scala:91)
at scala.io.Source$.fromFile(Source.scala:76)
at scala.io.Source$.fromFile(Source.scala:54)
... 32 elided

七、例外:Exception

類似於java
還是有一些變化

文件操作:
scala> val words = scala.io.Source.fromFile("H:\\tmp_files\\student.txt").mkString
words: String =
1 Tom 12
2 Mary 13
3 Lily 15

scala> val words = scala.io.Source.fromFile("H:\\tmp_files\\student1231312312312.txt").mkString
java.io.FileNotFoundException: H:\tmp_files\student1231312312312.txt (系統找不到指定的文件。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at scala.io.Source$.fromFile(Source.scala:91)
at scala.io.Source$.fromFile(Source.scala:76)
at scala.io.Source$.fromFile(Source.scala:54)
... 32 elided

見代碼

八、數組
1、數組的類型
(1)定長數組:Array
scala> val a = new Array[Int](10) -----> (10) 就是數組的長度
a: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

scala> val a = new Array[String](10)
a: Array[String] = Array(null, null, null, null, null, null, null, null, null, null)

初始化賦給默認值

scala> val c : Array[String] = Array("Tom","Lily")
c: Array[String] = Array(Tom, Lily)

scala> val c : Array[String] = Array("Tom","Lily",1)
<console>:11: error: type mismatch;
found : Int(1)
required: String
val c : Array[String] = Array("Tom","Lily",1)

不能往數組中添加不同類型的元素


(2)變長數組:ArrayBuffer

scala> val d = ArrayBuffer[Int]()
<console>:11: error: not found: value ArrayBuffer
val d = ArrayBuffer[Int]()
^

scala> import scala.collection.mutable._
import scala.collection.mutable._

scala> val d = ArrayBuffer[Int]()
d: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()

scala> d += 1
res2: d.type = ArrayBuffer(1)

scala> d += 2
res3: d.type = ArrayBuffer(1, 2)

scala> d += (1,2,3,4)
res4: d.type = ArrayBuffer(1, 2, 1, 2, 3, 4)

scala> d.
++ combinations groupBy mapResult reverse to
++: companion grouped max reverseIterator toArray
++= compose hasDefiniteSize maxBy reverseMap toBuffer
++=: contains hashCode min runWith toIndexedSeq
+: containsSlice head minBy sameElements toIterable
+= copyToArray headOption mkString scan toIterator
+=: copyToBuffer indexOf nonEmpty scanLeft toList
- corresponds indexOfSlice orElse scanRight toMap
-- count indexWhere padTo segmentLength toSeq
--= diff indices par seq toSet
-= distinct init partition size toStream
/: drop inits patch sizeHint toString
:+ dropRight insert permutations sizeHintBounded toTraversable
:\ dropWhile insertAll prefixLength slice toVector
<< endsWith intersect prepend sliding transform
WithFilter equals isDefinedAt prependAll sortBy transpose
addString exists isEmpty product sortWith trimEnd
aggregate filter isTraversableAgain readOnly sorted trimStart
andThen filterNot iterator reduce span union
append find last reduceLeft splitAt unzip
appendAll flatMap lastIndexOf reduceLeftOption startsWith unzip3
apply flatten lastIndexOfSlice reduceOption stringPrefix update
applyOrElse fold lastIndexWhere reduceRight sum updated
canEqual foldLeft lastOption reduceRightOption tail view
clear foldRight length reduceToSize tails withFilter
clone forall lengthCompare remove take zip
collect foreach lift repr takeRight zipAll
collectFirst genericBuilder map result takeWhile zipWithIndex

舉例:去掉數組中,最後兩個元素
scala> d
res5: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 1, 2, 3, 4)

scala> d.trimEnd(2)

scala> d
res7: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 1, 2)

遍歷數組:

for循環、foreach:
scala> var a = Array("Tom","Lily","Andy")
a: Array[String] = Array(Tom, Lily, Andy)

scala> for(s <- a ) println(s)
Tom
Lily
Andy

scala> a.foreach(println)
Tom
Lily
Andy

數組的常見操作舉例:
scala> val myarray = Array(1,2,7,8,10,3,6)
myarray: Array[Int] = Array(1, 2, 7, 8, 10, 3, 6)

scala> myarray.max
res10: Int = 10

scala> myarray.min
res11: Int = 1

scala> myarray.sortWith(_>_)
res12: Array[Int] = Array(10, 8, 7, 6, 3, 2, 1)

scala> myarray.sortWith(_<_)
res13: Array[Int] = Array(1, 2, 3, 6, 7, 8, 10)

解釋:(_>_)
完整 : sortWith函數裏面,參數也是一個函數 --> 高階函數

_>_ 函數

def comp(a:Int,b:Int) = {if(a>b) true else false}

(a,b) => {if(a>b) true else false}

(a,b) => {if(a>b) true else false} ----> _>_

_>_ 是一個函數,傳入兩個參數,返回值是bool

2、多維數組
和java類似,通過數組的數組來實現

scala> var matrix = Array.ofDim[Int](3,4)
matrix: Array[Array[Int]] = Array(Array(0, 0, 0, 0), Array(0, 0, 0, 0), Array(0, 0, 0, 0))

Array(0, 0, 0, 0)
Array(0, 0, 0, 0)
Array(0, 0, 0, 0)

三行四列的數組

scala> matrix(1)(2)=10

scala> matrix
res15: Array[Array[Int]] = Array(Array(0, 0, 0, 0), Array(0, 0, 10, 0), Array(0, 0, 0, 0))

數組下標是從0開始的

例子:
定義一個二維數組,其中每個元素是一個一維數組,並且長度不固定

scala> var triangle = new Array[Array[Int]](10)
triangle: Array[Array[Int]] = Array(null, null, null, null, null, null, null, null, null, null)

初始化:
scala> for(i <- 0 until triangle.length){
| triangle(i) = new Array[Int](i+1)
| }

scala> triangle
res17: Array[Array[Int]] = Array(Array(0), Array(0, 0), Array(0, 0, 0),
Array(0, 0, 0, 0), Array(0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0, 0, 0),
Array(0, 0, 0, 0, 0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0))

二維數組,如果使用 Array[Array[Int]](10) 聲明時:
1、首先指定的是外層數據的長度
2、初始化內層數組的時候,再指定內層數組的長度

九、映射 <key,value> Map

舉例:
創建一個map,來保存學生的成績

scala> val scores = Map("Tom" -> 80,"Andy"->70,"Mike"->90)
scores: scala.collection.mutable.Map[String,Int] = Map(Mike -> 90, Tom -> 80, Andy -> 70)

1、Map[String,Int] key String value Int
2、scala.collection.mutable

scala中,映射是有兩種,一種是可變map,一種是不可變map
scala.collection.mutable ---> 可變
scala.collection.immutable ---> 不可變

scala> val scores2 = scala.collection.immutable.Map("Tom" -> 80,"Andy"->70,"Mike"->90)
scores2: scala.collection.immutable.Map[String,Int] = Map(Tom -> 80, Andy -> 70, Mike -> 90)

映射的初始化:
scala> val scores2 = scala.collection.mutable.Map(("Tom",80),("Andy",70))
scores2: scala.collection.mutable.Map[String,Int] = Map(Tom -> 80, Andy -> 70)

scala> scores2=1
<console>:15: error: reassignment to val
scores2=1

映射的操作:

1、獲取映射中的值
scala> val chinese = scala.collection.mutable.Map(("Tom",80),("Andy",70))
chinese: scala.collection.mutable.Map[String,Int] = Map(Tom -> 80, Andy -> 70)

scala> chinese("Tom")
res18: Int = 80

scala> chinese.get("Andy")
res19: Option[Int] = Some(70)


scala> chinese("aaaa")
java.util.NoSuchElementException: key not found: aaaa
at scala.collection.MapLike$class.default(MapLike.scala:228)
at scala.collection.AbstractMap.default(Map.scala:59)
at scala.collection.mutable.HashMap.apply(HashMap.scala:65)
... 32 elided

scala> chinese.get("Andy1231312")
res21: Option[Int] = None


chinese("aaaa") get("Andy1231312")

需求:判斷key是否存在,若不存在,返回默認值

scala> if(chinese.contains("aaa")){
| chinese("aaa")
| }else{
| -1
| }
res22: Int = -1

scala> chinese.getOrElse("aaaa",-1)
res23: Int = -1


2、更新映射中的值

註意:必須是可變映射

scala> chinese
res24: scala.collection.mutable.Map[String,Int] = Map(Tom -> 80, Andy -> 70)

scala> chinese("Andy")=20

scala> chinese
res26: scala.collection.mutable.Map[String,Int] = Map(Tom -> 80, Andy -> 20)


3、映射的叠代
for foreach

scala> chinese
res27: scala.collection.mutable.Map[String,Int] = Map(Tom -> 80, Andy -> 20)

scala> for(s<-chinese) println(s)
(Tom,80)
(Andy,20)

scala> chinese.foreach(println)
(Tom,80)
(Andy,20)

foreach 高階函數

十、元組 : Tuple

scala 中的tuple : 是不同類型值的集合

scala> val t1 = Tuple("Tom","Lily",1)
<console>:14: error: not found: value Tuple
val t1 = Tuple("Tom","Lily",1)
^

scala> val t1 = Tuple3("Tom","Lily",1)
t1: (String, String, Int) = (Tom,Lily,1)

Tuple3 代表 Tuple中有三個元素

scala> val t1 = Tuple2("Lily",1)
t1: (String, Int) = (Lily,1)

scala> val t2 = (1,2,4,"Hello")
t2: (Int, Int, Int, String) = (1,2,4,Hello)


tuple操作:

訪問tuple中的元素


scala> val t1 = Tuple3("Tom","Lily",1)
t1: (String, String, Int) = (Tom,Lily,1)

scala> t1.
_1 _3 copy hashCode productArity productIterator toString zipped
_2 canEqual equals invert productElement productPrefix x

scala> t1._1
res30: String = Tom

scala> t1._3
res31: Int = 1


如何遍歷Tuple中的元素
註意:Tuple並沒有提供一個foreach函數,我們使用productIterator


遍歷分為兩步:
1、使用 productIterator 生成一個叠代器
2、遍歷

scala> t1.productIterator.
!= copyToBuffer forall min reduceRightOption toIterable
## corresponds foreach minBy sameElements toIterator
+ count formatted mkString scanLeft toList
++ drop getClass ne scanRight toMap
-> dropWhile grouped next seq toSeq
/: duplicate hasDefiniteSize nonEmpty size toSet
:\ ensuring hasNext notify slice toStream
== eq hashCode notifyAll sliding toString
GroupedIterator equals indexOf padTo span toTraversable
addString exists indexWhere partition sum toVector
aggregate filter isEmpty patch synchronized wait
asInstanceOf filterNot isInstanceOf product take withFilter
buffered find isTraversableAgain reduce takeWhile zip
collect flatMap length reduceLeft to zipAll
collectFirst fold map reduceLeftOption toArray zipWithIndex
contains foldLeft max reduceOption toBuffer →
copyToArray foldRight maxBy reduceRight toIndexedSeq

scala> t1.productIterator.foreach(println)
Tom
Lily
1

十一、scala中的文件操作
類似於java的io
舉例:
1、讀取文件
2、讀取二進制文件
3、從url中獲取信息
4、寫入文件

5、scala中調用java的類庫

見代碼

---------------Scala面向對象--------------------------

scala是一個多範式的編程語言(支持多種方式的編程)
類似於 java 有區別

一、面向對象的概念
1、封裝 : 把屬性和操作屬性的方法,寫在了一起。class
2、繼承
3、多態

java中面向對象的概念,也是用與scala

二、定義類:class

舉例:創建一個學生類

三、內部類(嵌套類):在一個類的內部,定義了另外一個類

見代碼

四、類的構造器:兩種
1、主構造器 : 和類的聲明在一起,並且一個類只能有一個主構造器

class Course(var courseName:String,var grade : Int)

2、輔助構造器 : 一個類可以有多個輔助構造器,通過this來實現

五、object對象:相當於java中的static

1、Object 對象中的內容都是靜態的
2、如果和類名相同,則成為伴生對象
3、scala中沒有static關鍵字

4、舉例
(1)使用object來實現單例模式:一個類裏面只有一個對象
在java中,把類的構造器定義成private的,並且提供一個getInstance,返回對象
在scala中,使用object實現

(2)使用App對象:應用程序對象。
好處:可以省略main方法。

六、apply方法
val t1 = Tuple3("Tom","Lily",1)
沒有new關鍵字,但是也創建出來對象,用了apply方法

註意:apply方法必須寫在伴生對象中。

七、繼承
1、extends 和java一樣
object HelloWorld extends App

2、抽象類:代碼中


抽象字段:

package day0323

/**
* Created by root on 2019/3/23.
*
* 抽象字段 抽象屬性
*
* 定義: 沒有初始值的字段
*/

abstract class Person1{
//定義抽象字段
val id :Int
val name : String
}

如果不加abstract 報錯
abstract class Employee1 extends Person1{

}

下面兩種方式均不會報錯

class Employee2() extends Person1{
val id :Int = 1
val name : String = ""
}

class Employee2(val id:Int,val name:String) extends Person1{

}

object Demo3 {

}

八、特質(trait): 抽象類,支持多重繼承

本質:scala 的一個抽象類
trait

關鍵字:extends Human with Action

九、包和包對象:參考講義
package
package object

---------------Scala函數式編程--------------------------

多範式:面向對象,函數式編程(程序實現起來簡單)

舉例:WordCount
sc 是 SparkContext , 非常重要

一行:

var result =
sc.textFile("hdfs://xxxx/xxx/data.txt")
.flatMap(_.split(" "))
.map((_,1))
.reduceByKey(_+_)
.collect

一、復習函數:關鍵字 def

二、匿名函數:沒有名字的函數
舉例:
scala> var myarray = Array(1,2,3)
myarray: Array[Int] = Array(1, 2, 3)

scala> def fun1(x:Int):Int = x*3
fun1: (x: Int)Int

scala> (x:Int) => x*3
res0: Int => Int = <function1>

問題:怎麽去調用?高階函數
scala> fun1(3)
res1: Int = 9

scala> myarray.foreach(println)
1
2
3

scala> myarray.map((x:Int) => x*3)
res3: Array[Int] = Array(3, 6, 9)
(_,1) (_+_) 都是匿名函數。

三、高階函數(帶有函數參數的函數):把一個函數作為另外一個函數的參數值

定義一個高階函數:
對10做某種運算
scala> def someAction(f:(Double)=>(Double)) = f(10)
someAction: (f: Double => Double)Double

解釋:
(Double)=>(Double) 代表了f 的類型:入參是double,返回值也是double的函數

scala> someAction(sqrt)
res5: Double = 3.1622776601683795

scala> someAction(sin)
res6: Double = -0.5440211108893698

scala> someAction(cos)
res7: Double = -0.8390715290764524

scala> someAction(println)
<console>:16: error: type mismatch;
found : () => Unit
required: Double => Double
someAction(println)
^
def someAction(f:(Double)=>(Double)) = f(10)

someAction(sqrt) = sqrt(10)

四、高階函數的實例
scala中提供了常用的高階函數。

(*)map : 相當於一個循環,對某個集合中的每個元素都進行操作(接收一個函數),返回一個新的集合。

scala> var numers = List(1,2,3,4,5,6,7,8,9,10)
numers: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> numers.map((i:Int)=>i*2)
res9: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)

scala> numers.map(_*2)
res10: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)

說明:
(i:Int)=>i*2 與 _*2 等價的。

(i:Int,j:Int)=>i+j _+_

scala> numers
res11: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

不改變numbers本身的值。

(*)foreach:相當於一個循環,對某個集合中的每個元素都進行操作(接收一個函數),不返回結果。
scala> numers.foreach(println)
1
2
3
4
5
6
7
8
9
10

numers.foreach(_*2)
沒有返回值。


(*) filter :過濾,選擇滿足的數據
舉例:查詢能被2整除的數字

scala> numers.filter((i:Int)=>i%2==0)
res14: List[Int] = List(2, 4, 6, 8, 10)

filter函數,參數要求:要求一個返回 bool 值的函數,篩選出所有為true的數據。

(*)zip操作:合並兩個集合

scala> numers.filter((i:Int)=>i%2==0)
res14: List[Int] = List(2, 4, 6, 8, 10)

scala> List(1,2,3).zip(List(4,5,6))
res15: List[(Int, Int)] = List((1,4), (2,5), (3,6))

scala> List(1,2,3).zip(List(4,5))
res16: List[(Int, Int)] = List((1,4), (2,5))

scala> List(1).zip(List(4,5))
res17: List[(Int, Int)] = List((1,4))

(*)partition : 根據斷言(就是某個條件,匿名函數)的結果,來進行分區

舉例:能被2整除的分成一個區,不能被2整除的分成另外一個區。

scala> numers.partition((i:Int)=>i%2==0)
res18: (List[Int], List[Int]) = (List(2, 4, 6, 8, 10),List(1, 3, 5, 7, 9))

(*)find : 查找第一個滿足條件的元素

scala> numers.find(_%3==0)
res19: Option[Int] = Some(3)

_%3==0 (i:Int)=>i%3==0 一樣

(*)flatten:把嵌套的結果展開
scala> List(List(2,4,6,8,10),List(1,3,5,7,9)).flatten
res21: List[Int] = List(2, 4, 6, 8, 10, 1, 3, 5, 7, 9)


(*)flatmap : 相當於一個 map + flatten

scala> var myList = List(List(2,4,6,8,10),List(1,3,5,7,9))
myList: List[List[Int]] = List(List(2, 4, 6, 8, 10), List(1, 3, 5, 7, 9))

scala> myList.flatMap(x=>x.map(_*2))
res22: List[Int] = List(4, 8, 12, 16, 20, 2, 6, 10, 14, 18)

myList.flatMap(x=>x.map(_*2))

執行過程:
1、將 List(2, 4, 6, 8, 10), List(1, 3, 5, 7, 9) 調用 map(_*2) 方法。x 代表一個List
2、flatten

五、概念:閉包、柯裏化

1、閉包:就是函數的嵌套
在一個函數的裏面,包含了另一個函數的定義
可以在內函數中訪問外函數的變量

舉例:
def mulBy(factor:Double) = (x:Double)=>x*factor
外 內

乘以三:
scala> def mulBy(factor:Double) = (x:Double)=>x*factor
mulBy: (factor: Double)Double => Double

scala> var triple = mulBy(3)
triple: Double => Double = <function1>

相當於 triple(x:Double) = x*3

scala> triple(10)
res23: Double = 30.0

scala> triple(20)
res24: Double = 60.0

scala> var half = mulBy(0.5)
half: Double => Double = <function1>

scala> half(10)
res25: Double = 5.0

引入柯裏化:
scala> mulBy(3)(10)
res26: Double = 30.0

2、柯裏化
概念:柯裏化函數:是把具有多個參數的函數,轉化為一個函數鏈,每個節點上都是單一函數

def add(x:Int,y:Int) = x+y

def add(x:Int)(y:Int) = x+y

轉化步驟:

原始:def add(x:Int,y:Int) = x+y

閉包:def add(x:Int) = (y:Int) => x+y

簡寫:def add(x:Int)(y:Int) = x+y

scala> def add(x:Int)(y:Int) = x+y
add: (x: Int)(y: Int)Int

scala> add(1)(2)
res27: Int = 3

---------------Scala集合-------------------------

比較簡單

1、可變集合和不可變集合(Map)

immutable mutable
舉例:

scala> def math = scala.collection.immutable.Map("Tom"->80,"Lily"->20)
math: scala.collection.immutable.Map[String,Int]

scala> def math = scala.collection.mutable.Map("Tom"->80,"Lily"->20,"Mike"->95)
math: scala.collection.mutable.Map[String,Int]

集合的操作:
獲取集合中的值

scala> math.get("Tom")
res28: Option[Int] = Some(80)

scala> math("Tom")
res29: Int = 80

scala> math("Tom12312312")
java.util.NoSuchElementException: key not found: Tom12312312
at scala.collection.MapLike$class.default(MapLike.scala:228)
at scala.collection.AbstractMap.default(Map.scala:59)
at scala.collection.mutable.HashMap.apply(HashMap.scala:65)
... 32 elided

scala> math.get("Tom123123123")
res31: Option[Int] = None

scala> math.contains("Tom123123123")
res32: Boolean = false

scala> math.getOrElse("Tom123123123",-1)
res33: Int = -1


更新集合中的值:註意:必須是可變集合

scala> math
res34: scala.collection.mutable.Map[String,Int] = Map(Mike -> 95, Tom -> 80, Lily -> 20)

scala> math("Tom")=0

scala> math
res36: scala.collection.mutable.Map[String,Int] = Map(Mike -> 95, Tom -> 80, Lily -> 20)

造成上述現象的原因,沒有import包,如果import以後,問題解決:

scala> import scala.collection.mutable._
import scala.collection.mutable._

scala> var math = Map("Tom"->80,"Lily"->20,"Mike"->95)
math: scala.collection.mutable.Map[String,Int] = Map(Mike -> 95, Tom -> 80, Lily -> 20)

scala> math("Tom")=0

scala> math
res1: scala.collection.mutable.Map[String,Int] = Map(Mike -> 95, Tom -> 0, Lily -> 20)


添加新的元素

scala> math += "Bob"->85
res38: scala.collection.mutable.Map[String,Int] = Map(Bob -> 85, Mike -> 95, Tom -> 80, Lily -> 20)

移出一個元素
scala> math -= "Bob"
res39: scala.collection.mutable.Map[String,Int] = Map(Mike -> 95, Tom -> 80, Lily -> 20)

2、列表:可變列表,不可變列表

不可變列表 List

scala> myList.head
res40: Int = 1

scala> myList.tail
res41: List[Int] = List(2, 3)

註意:tail 是除了第一個元素外,其他的元素

可變列表:LinedList 在 scala.collection.mutable 包中

scala> var myList = scala.collection.mutable.LinkedList(1,2,3,4)
warning: there was one deprecation warning; re-run with -deprecation for details
myList: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3, 4)

需求:把上面列表中,每一個元素都乘以2

遊標,指向列表的開始

var cur = myList

while(cur != Nil ){

//把當前元素乘以2
cur.elem = cur.elem*2

//移動指針到下一個元素
cur = cur.next
}

scala> var cur = myList
cur: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3, 4)

scala> while(cur != Nil ){
| cur.elem = cur.elem*2
| cur = cur.next
| }

scala> myList
res43: scala.collection.mutable.LinkedList[Int] = LinkedList(2, 4, 6, 8)

scala> myList.map(_*2)
warning: there was one deprecation warning; re-run with -deprecation for details
res44: scala.collection.mutable.LinkedList[Int] = LinkedList(4, 8, 12, 16)

3、序列
(*)數據庫中也有序列:sequence 、 auto increment
(1)作為主鍵,實現自動增長
(2)提高性能,序列在Oracle是在內存中的

(*)Vector Range

舉例:
Vector 是一個帶下標的序列,我們可以通過下標來訪問Vector中的元素

Range : 是一個整數的序列
scala> Range(0,5)
res45: scala.collection.immutable.Range = Range(0, 1, 2, 3, 4)

從0開始,到5 ,但不包括5

scala> println(0 until 5)
Range(0, 1, 2, 3, 4)

scala> println(0 to 5)
Range(0, 1, 2, 3, 4, 5)

Range可以相加
scala> (‘0‘ to ‘9‘) ++ (‘A‘ to ‘Z‘)
res48: scala.collection.immutable.IndexedSeq[Char] = Vector(0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U
, V, W, X, Y, Z)

把Range轉換成list
scala> 1 to 5 toList
warning: there was one feature warning; re-run with -feature for details
res49: List[Int] = List(1, 2, 3, 4, 5)

4、集(Set) : 不重復元素的集合,默認是HashSet,與java類似
scala> var s1 = Set(1,2,10,8)
s1: scala.collection.immutable.Set[Int] = Set(1, 2, 10, 8)

scala> s1 + 10
res50: scala.collection.immutable.Set[Int] = Set(1, 2, 10, 8)

scala> s1 + 7
res51: scala.collection.immutable.Set[Int] = Set(10, 1, 2, 7, 8)

scala> s1
res52: scala.collection.immutable.Set[Int] = Set(1, 2, 10, 8)

創建一個可排序的Set SortedSet

scala> var s2 = scala.collection.mutable.SortedSet(1,2,3,10,8)
s2: scala.collection.mutable.SortedSet[Int] = TreeSet(1, 2, 3, 8, 10)

判斷元素是否存在
scala> s2.contains(1)
res53: Boolean = true

scala> s2.contains(1231231)
res54: Boolean = false

集的運算:union並集 intersect 交集 diff 差集
scala> var s1 = Set(1,2,3,4,5,6)
s1: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3, 4)

scala> var s2 = Set(5,6,7,8,9,10)
s2: scala.collection.immutable.Set[Int] = Set(5, 10, 6, 9, 7, 8)

scala> s1 union s2
res55: scala.collection.immutable.Set[Int] = Set(5, 10, 1, 6, 9, 2, 7, 3, 8, 4)

scala> s1 intersect s2
res56: scala.collection.immutable.Set[Int] = Set(5, 6)

scala> s1 diff s2
res57: scala.collection.immutable.Set[Int] = Set(1, 2, 3, 4)

數據庫裏面的union操作,要求:
列數一樣
列的類型一樣

select A,B from ****
union
select C,D from *****

python
pyspark

5、模式匹配

6、樣本類














scala的面向對象,繼承與特質