從頭學習大數據培訓課程 scala 對象與函數式編程(二)scala 基礎 2
lazy關鍵字
惰性變數用法放在不可變變數之前只有在調用惰性變數時才會去實例化這個變數,類似於java中單例模式的懶漢模式object LazyDemo {def init():Unit = { println("init") } def main(args: Array[String]): Unit = {val property = init() //沒有lzay關鍵字的時候 println("init after") println(property) } }object LazyDemo2{def init():Unit = { println("init") }def main(args: Array[String]): Unit = { lazy val property = init() //有lzay關鍵字的時候,在調用的時候才去初化它 println("init after") println(property) } }
集合高級操作:
object ListDemo {def main(args: Array[String]): Unit = {val list0 = List(1, 2, 3, 4, 5, 6, 7, 8) //循環每一個元素並按函數的結果生成新的集合val list1 = list0.map(_ * 2) //循環每一個元素並按進行過濾,過濾掉不滿足條件的,返回新的集合val list2 = list0.filter(_ % 2 == 0) //集合升序val list3 = list0.sorted//集合倒序val list4 = list3.reverse//集合里的元素每幾個分成一組val it = list0.grouped(2) //將迭代器轉成可變數組 //val list5 = it.toBuffer // println(list5) //將迭代器轉成不可變序列,注意迭代器的循環在調用it.toBuffer // 或it.toList循環到結尾所以在第一次調用的時候就把值全取出來了val list6 = it.toList//將list重新組合val list7 = list6.flatten val list8 = List("a b c", "d e f") val list9 = list8.map(_.split(" ")) //將Array[String]進重新組合,不支持元組 val list10 = list9.flatten//flatMap等於map和flatten的結合val list11 = list8.flatMap(_.split(" ")) //利用機器的空閑線程進行並行計算,也就是每個線程拿一部分數據進行並行求合, // 最後再進行匯總和mr的wordcount類似val res = list0.par.sum //普通的求合 val res1 = list0.sum//按照List里從頭到尾的順序進行累加,就是從左向右加val res2 = list0.reduce(_ + _) val res3 = list0.reduceLeft(_ + _) val res4 = list0.reduceRight(_ + _) //用結果演示是否並行化,分的線程不一樣,結果也就不一樣,因為每個線程拿到的數據都是隨機的val res5 = list0.par.reduce(_ - _) //結定初始值為10,然後進行每一項的累加 val res6 = list0.fold(10)(_ + _) val res66 = list0.fold(10)(_ - _) //給定初始值為10,然後累加每一項,分的線程不一樣,結果也就不一樣 val res7 = list0.par.fold(10)(_ + _) //按特定順序進行操作 val res8 = list0.foldLeft(10)(_ + _) val res9 = list0.foldRight(10)(_ + _) val res10 = list0.foldLeft(10)(_ - _) val res11 = list0.foldRight(10)(_ - _) //因為這裡par使用的是foldLeft所以是有特定順序的 val res12 = list0.par.foldLeft(10)(_ - _)val list12 = List(List(1, 2), List(1, 3), List(3, 4, 5), List(2)) // val res13 = list12.reduce(_.sum + _.sum) //聚合操作 // val res14 = list12.aggregate(0)((a,q) => {println(a + "," + q.sum);a + q.sum},(a ,b) => a) val res14 = list12.aggregate(0)(_ + _.sum, _ + _) val res13 = list12.foldLeft(0)(_ + _.sum) //aggregate沒有被par調用時第2個參數並沒有參與運算val res18 = list12.par.aggregate(0)((a,q) => {println(a + "," + q.sum);a + q.sum}, (a,b) => {println(a + "," + b);a + b}) println(res18) //並集 val res15 = List(1,2) union List(3,4) //交集 val res16 = List(1,2) intersect List(1,5) //差集 val res17 = List(1,2) diff List(1) println(res15) println(res16) println(res17) } }
wordcount
object WordCount {def main(args: Array[String]): Unit = {val lines = List("a b c d","a d e s","a b d e","a a a b") //切分並生成一個list val words = lines.flatMap(_.split(" ")) //把每個單詞生成 (自身,1) 的元組val tuples = words.map((_ -> 1)) //以key(單詞)進行分組val group = tuples.groupBy(_._1) //統計每組key的values的長度val mapValue = group.mapValues(_.size) //升序val list = mapValue.toList.sortBy(_._2) //降序 val result = list.reverseprintln(result) } }
類scala中類的關鍵字默認就是public的,所以如果是public的則不需要加訪問限制關鍵字一個類文件可以聲明多個類
語法:
class 類名{}
靜態類object 類名{}
如果類名和靜態類的類名相同那這個靜態類就叫做這個類的伴生對象
類中的屬性:
可以分為可變(var)和不可變(val)訪問修飾可以分private和private[this]示例:
class ClassDemo { //用val修改的變數是只讀的,相當只有get方法,沒有set方法val name: String = "hainiu" //用var修飾的變數相當於既有get又有set方法 var gender: String = _//用private修飾的屬性,該屬性屬於對象私有變數,只有本類和伴生對象能訪問到 private var age: Int = _//用private[this]修飾後,該屬性屬於對象私有變數,只有本類才能訪問,伴生對象也訪問不到, //注意這個變數並沒有指定類型這裡是scala自己根據值進行推斷的 private[this] val location = "北京" } /*** 類ClassDemo的伴生對象*/object ClassDemo {def main(args: Array[String]): Unit = {val demo = new ClassDemo //demo.name = "hainiu1" println(demo.name) println(demo.gender)demo.gender = "男" println(demo.gender) println(demo.age) // println(demo.location) } } /*** 其它對象*/object ClassDemo1{def main(args: Array[String]): Unit = {val demo = new ClassDemo // demo.name = "hainiu1" println(demo.name) println(demo.gender)demo.gender = "男" println(demo.gender) // println(demo.age) // println(demo.location) } }
構造器:
用於對類進行屬性的初始化,分為主構造器和輔助構造器1).主構造器用法:
語法://參數可以有默認值class 類名(參數列表){}
示例:
class ConDemo(val name: String, var age: Int, location: String = "北京") {def getLocation():String={ //不可能進行修改因為是被當成val修飾的 // location = "上海" //如果沒有寫return那最後一句代碼的值就被做為返回location} }object ConDemo {def main(args: Array[String]): Unit = { //因為location有默認值,所以調用構造函數的時候可以不用寫val demo = new ConDemo("hainiu", 1) //不能改因為是val修飾的 //demo.name = "hai1niu"demo.age = 100 println(demo.name) println(demo.age) //不能訪問因為沒有val或var修飾,就相當於是用private[this] val修飾的屬性,要訪問只能自己寫相應的get方法 // println(demo.location) } }
2).輔助構造器用法:
語法:
//輔助構造器中使用的變數進行聲明
var a:String = _def this([輔助構造器參數列表...],a:String){
this(主構造器參數列表) //看自己的情況來定是否輔助構造器參數列表與主構造器參數列相同this.a = a //這個a變數需要在class中進行聲明,不然提示找不到這個變數}示例:
class ConDemo1(val name:String,var age:Int,location:String = "北京") {def getLocation:String = {location} var gender:String = _/*** 輔助構造器*/def this(name:String,age:Int,location:String,gender:String){ //輔助構造器第一行必須要先調用主構造器 this(name,age,location)this.gender = gender} }object ConDemo1{def main(args: Array[String]): Unit = {val demo = new ConDemo1("hainiu",1,"上海","男") println(demo.name) println(demo.age) println(demo.getLocation) println(demo.gender) } }
總結:
主構造器的參數列表要放到類名的後面,和類名放在一起,val修飾的構造參數具有不可變性,var修飾的構造參數具有可變性如果參數沒有用val或var修飾那它既不可被外面直接方問(可通過相應的get方法訪問)只能在本類中使用,伴生對象也無法使用,也不可在本類中進行修改因為它被當成隱藏的val修飾的
輔助構造器可以沒有,如果有要在類中進行定義,輔助構造器可以聲明主構造器沒有的參數,如果聲明了其它參數那這個參數需要在類中進行定義,否則提示無法找到這個參數
輔助構造器也可以理解成java中的構造器重載,且輔助構造器的第一行必須要先調用主構造器(這點和python的基礎調用父類比較相似)idea使用:
如果按ctrl+p,提示有兩行或多行的時候那就說明有鋪裝構造器
快捷鍵修改
單例對象在scala中沒有像java一樣的static關鍵字在scala中是沒有靜態方法和靜態欄位的,但是可以使用object關鍵字加類名的語法結構實現同樣的功能
在scala中用object修飾的為單例對象,單例對象中主要存放常量和工具方法示例:
import scala.collection.mutable.ArrayBufferobject Single{def main(args: Array[String]): Unit = {val factory = SingleFactoryprintln(factory.getSession) println(factory.getSession.size) println(factory.getSession(0)) println(factory.removeSession) println(factory.getSession.size) } }object SingleFactory { /*** 相當於java中的靜態塊*/ println("SingleFactory Init") var i = 5 private val session = ArrayBuffer[A]() while(i > 0){session += new A()i -= 1 }def getSession = sessiondef removeSession:Unit ={val s = session(0)session.remove(0) println(s"session被移除$s") } } class A{}
伴生對象
特徵:一個單例對象未必是一個伴生對象,但是一個伴生對象一定是一個單例對象與類名相同並且用Object修飾的對象叫做伴生對象,類和伴生對象之間可以互相訪問對方的私有方法和屬性示例
class Cat{ private var name:String = "lanmao" println(Cat.skill) private def action():Unit = { println(name + "_" + Cat.skill) } }object Cat{ private val skill = "撓人"def main(args: Array[String]): Unit = {val c = new Cat() println(c.name)c.name = "tumao"c.action() } }
版權聲明:原創作品,允許轉載,轉載時務必以超鏈接的形式表明出處和作者信息。否則將追究法律責任。來自海牛學院-青牛
推薦閱讀:
※kylin 同步原理及加入重試邏輯
※kylin 同步問題的patch被採納
※《大數據導論》讀書筆記——Chapter 6
※李強「大數據分析社群」學習旅途計劃
※國外SaaS圖譜之商業智能BI(持續更新)