1. 程式人生 > >scala的面向對象,類與構造器

scala的面向對象,類與構造器

內部類 tle abs orelse sql puts 返回對象 配置環境 sts


---------------------------------------------------------------------------------------
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 {

}



















scala的面向對象,類與構造器