Scala介紹 html
1.Spark中使用的是Sacla2.10。 java
2.Scala官網6個特徵。 程序員
1).Java和scala能夠混編 apache
2).類型推測(自動推測類型) windows
4).特質,特徵(相似java中interfaces 和 abstract結合) 多線程
5).模式匹配(相似java switch) 併發
6).高階函數 app
Scala安裝使用 eclipse
;%SCALA_HOME%\bin;%SCALA_HOME%\jre\bin
http://scala-ide.org/download/prev-stable.html
點擊第三步,彈出選擇SDK,點擊Browse選擇本地安裝的Scala目錄。選擇system.
Scala基礎
/** * 定義變量和常量 * 變量 :用 var 定義 ,可修改 * 常量 :用 val 定義,不可修改 */ var name = "zhangsan" println(name) name ="lisi" println(name) val gender = "m" // gender = "m"//錯誤,不能給常量再賦值 |
class Person{ val name = "zhangsan" val age = 18 def sayName() = { "my name is "+ name } } |
object Lesson_Class { def main(args: Array[String]): Unit = { val person = new Person() println(person.age); println(person.sayName()) } } |
class Person(xname :String , xage :Int){ var name = Person.name val age = xage var gender = "m" def this(name:String,age:Int,g:String){ this(name,age) gender = g }
def sayName() = { "my name is "+ name }
}
object Person { val name = "zhangsanfeng"
def main(args: Array[String]): Unit = { val person = new Person("wagnwu",10,"f") println(person.age); println(person.sayName()) println(person.gender) } } |
注意點:
重寫構造函數的時候,必需要調用默認的構造函數。
/** * if else */ val age =18 if (age < 18 ){ println("no allow") }else if (18<=age&&age<=20){ println("allow with other") }else{ println("allow self") } |
/** * to和until * 例: * 1 to 10 返回1到10的Range數組,包含10 * 1 until 10 返回1到10 Range數組 ,不包含10 */
println(1 to 10 )//打印 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 println(1.to(10))//與上面等價,打印 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
println(1 to (10 ,2))//步長爲2,從1開始打印 ,1,3,5,7,9 println(1.to(10, 2))
println(1 until 10 ) //不包含最後一個數,打印 1,2,3,4,5,6,7,8,9 println(1.until(10))//與上面等價
println(1 until (10 ,3 ))//步長爲2,從1開始打印,打印1,4,7 |
/** * for 循環 * */ for( i <- 1 to 10 ){ println(i) } |
//能夠分號隔開,寫入多個list賦值的變量,構成多層for循環 //scala中 不能寫count++ count-- 只能寫count+ var count = 0; for(i <- 1 to 10; j <- 1 until 10){ println("i="+ i +", j="+j) count += 1 } println(count);
//例子: 打印小九九 for(i <- 1 until 10 ;j <- 1 until 10){ if(i>=j){ print(i +" * " + j + " = "+ i*j+" ")
} if(i==j ){ println() }
} |
//能夠在for循環中加入條件判斷 for(i<- 1 to 10 ;if (i%2) == 0 ;if (i == 4) ){ println(i) } |
//將for中的符合條件的元素經過yield關鍵字返回成一個集合 val list = for(i <- 1 to 10 ; if(i > 5 )) yield i for( w <- list ){ println(w) }
/** * while 循環 */ var index = 0 while(index < 100 ){ println("第"+index+"次while 循環") index += 1 } index = 0 do{ index +=1 println("第"+index+"次do while 循環") }while(index <100 ) |
Scala函數
def fun (a: Int , b: Int ) : Unit = { println(a+b) } fun(1,1)
def fun1 (a : Int , b : Int)= a+b println(fun1(1,2)) |
注意點:
/** * 遞歸函數 * 5的階乘 */ def fun2(num :Int) :Int= { if(num ==1) num else num * fun2(num-1) } print(fun2(5)) |
/** * 包含默認參數值的函數 * 注意: * 1.默認值的函數中,若是傳入的參數個數與函數定義相同,則傳入的數值會覆蓋默認值 * 2.若是不想覆蓋默認值,傳入的參數個數小於定義的函數的參數,則須要指定參數名稱 */ def fun3(a :Int = 10,b:Int) = { println(a+b) } fun3(b=2) |
/** * 可變參數個數的函數 * 注意:多個參數逗號分開 */ def fun4(elements :Int*)={ var sum = 0; for(elem <- elements){ sum += elem } sum } println(fun4(1,2,3,4)) |
/** * 匿名函數 * 1.有參數匿名函數 * 2.無參數匿名函數 * 3.有返回值的匿名函數 * 注意: * 能夠將匿名函數返回給定義的一個變量 */ //有參數匿名函數 val value1 = (a : Int) => { println(a) } value1(1) //無參數匿名函數 val value2 = ()=>{ println("我愛尚學堂") } value2() //有返回值的匿名函數 val value3 = (a:Int,b:Int) =>{ a+b } println(value3(4,4)) |
/** * 嵌套函數 * 例如:嵌套函數求5的階乘 */ def fun5(num:Int)={ def fun6(a:Int,b:Int):Int={ if(a == 1){ b }else{ fun6(a-1,a*b) } } fun6(num,1) } println(fun5(5)) |
偏應用函數是一種表達式,不須要提供函數須要的全部參數,只須要提供部分,或不提供所需參數。
/** * 偏應用函數 */ def log(date :Date, s :String)= { println("date is "+ date +",log is "+ s) }
val date = new Date() log(date ,"log1") log(date ,"log2") log(date ,"log3")
//想要調用log,以上變化的是第二個參數,能夠用偏應用函數處理 val logWithDate = log(date,_:String) logWithDate("log11") logWithDate("log22") logWithDate("log33") |
函數的參數是函數,或者函數的返回類型是函數,或者函數的參數和函數的返回類型是函數的函數。
/** * 高階函數 * 函數的參數是函數 或者函數的返回是函數 或者函數的參數和返回都是函數 */
//函數的參數是函數 def hightFun(f : (Int,Int) =>Int, a:Int ) : Int = { f(a,100) } def f(v1 :Int,v2: Int):Int = { v1+v2 }
println(hightFun(f, 1))
//函數的返回是函數 //1,2,3,4相加 def hightFun2(a : Int,b:Int) : (Int,Int)=>Int = { def f2 (v1: Int,v2:Int) :Int = { v1+v2+a+b } f2 } println(hightFun2(1,2)(3,4))
//函數的參數是函數,函數的返回是函數 def hightFun3(f : (Int ,Int) => Int) : (Int,Int) => Int = { f } println(hightFun3(f)(100,200)) println(hightFun3((a,b) =>{a+b})(200,200)) //以上這句話還能夠寫成這樣 //若是函數的參數在方法體中只使用了一次 那麼能夠寫成_表示 println(hightFun3(_+_)(200,200)) |
/** * 柯里化函數 */ def fun7(a :Int,b:Int)(c:Int,d:Int) = { a+b+c+d } println(fun7(1,2)(3,4)) |
Scala字符串
/** * String && StringBuilder */ val str = "abcd" val str1 = "ABCD"
println(str.indexOf(97)) println(str.indexOf("b"))
println(str==str1) /** * compareToIgnoreCase * * 若是參數字符串等於此字符串,則返回值 0; * 若是此字符串小於字符串參數,則返回一個小於 0 的值; * 若是此字符串大於字符串參數,則返回一個大於 0 的值。 * */ println(str.compareToIgnoreCase(str1))
val strBuilder = new StringBuilder strBuilder.append("abc") // strBuilder.+('d') strBuilder+ 'd' // strBuilder.++=("efg") strBuilder++= "efg" // strBuilder.+=('h') strBuilder+= 'h' strBuilder.append(1.0) strBuilder.append(18f) println(strBuilder)
|
String方法:(見附件)
集合
數組
賦值:arr(0) = xxx
建立兩種方式:
/** * 建立數組兩種方式: * 1.new Array[String](3) * 2.直接Array */
//建立類型爲Int 長度爲3的數組 val arr1 = new Array[Int](3) //建立String 類型的數組,直接賦值 val arr2 = Array[String]("s100","s200","s300") //賦值 arr1(0) = 100 arr1(1) = 200 arr1(2) = 300 |
遍歷兩種方式:
/** * 遍歷兩種方式 */ for(i <- arr1){ println(i) } arr1.foreach(i => { println(i) })
for(s <- arr2){ println(s) } arr2.foreach { x => println(x) }
|
建立二維數組
/** * 建立二維數組和遍歷 */ val arr3 = new Array[Array[String]](3) arr3(0)=Array("1","2","3") arr3(1)=Array("4","5","6") arr3(2)=Array("7","8","9") for(i <- 0 until arr3.length){ for(j <- 0 until arr3(i).length){ print(arr3(i)(j)+" ") } println() }
var count = 0 for(arr <- arr3 ;i <- arr){ if(count%3 == 0){ println() } print(i+" ") count +=1 }
arr3.foreach { arr => { arr.foreach { println } }}
val arr4 = Array[Array[Int]](Array(1,2,3),Array(4,5,6)) arr4.foreach { arr => { arr.foreach(i => { println(i) }) }} println("-------") for(arr <- arr4;i <- arr){ println(i) }
|
數組中的方法:
list
val list = List(1,2,3,4)
foreach ,for
//建立 val list = List(1,2,3,4,5)
//遍歷 list.foreach { x => println(x)} // list.foreach { println} //filter val list1 = list.filter { x => x>3 } list1.foreach { println}
//count val value = list1.count { x => x>3 } println(value)
//map val nameList = List( "hello bjsxt", "hello xasxt", "hello shsxt" ) val mapResult:List[Array[String]] = nameList.map{ x => x.split(" ") } mapResult.foreach{println}
//flatmap val flatMapResult : List[String] = nameList.flatMap{ x => x.split(" ") } flatMapResult.foreach { println } |
set
注意:set集合會自動去重
foreach,for
//建立 val set1 = Set(1,2,3,4,4) val set2 = Set(1,2,5) //遍歷 //注意:set會自動去重 set1.foreach { println} for(s <- set1){ println(s) } println("*******") /** * 方法舉例 */
//交集 val set3 = set1.intersect(set2) set3.foreach{println} val set4 = set1.&(set2) set4.foreach{println} println("*******") //差集 set1.diff(set2).foreach { println } set1.&~(set2).foreach { println } //子集 set1.subsetOf(set2)
//最大值 println(set1.max) //最小值 println(set1.min) println("****")
//轉成數組,list set1.toArray.foreach{println} println("****") set1.toList.foreach{println}
//mkString println(set1.mkString) println(set1.mkString("\t"))
|
set方法總結
map
注意:建立map時,相同的key被後面的相同的key頂替掉,只保留一個
val map = Map( "1" -> "bjsxt", 2 -> "shsxt", (3,"xasxt") ) |
//獲取值 println(map.get("1").get) val result = map.get(8).getOrElse("no value") println(result) |
//map遍歷 for(x <- map){ println("====key:"+x._1+",value:"+x._2) } map.foreach(f => { println("key:"+ f._1+" ,value:"+f._2) }) |
//遍歷key val keyIterable = map.keys keyIterable.foreach { key => { println("key:"+key+", value:"+map.get(key).get) } } println("---------")
|
//遍歷value val valueIterable = map.values valueIterable.foreach { value => { println("value: "+ value) } }
|
注意:合併map會將map中的相同key的value替換
//合併map val map1 = Map( (1,"a"), (2,"b"), (3,"c") ) val map2 = Map( (1,"aa"), (2,"bb"), (2,90), (4,22), (4,"dd") ) map1.++:(map2).foreach(println)
|
/** * map方法 */ //count val countResult = map.count(p => { p._2.equals("shsxt") }) println(countResult)
//filter map.filter(_._2.equals("shsxt")).foreach(println)
//contains println(map.contains(2))
//exist println(map.exists(f =>{ f._2.equals("xasxt")
}))
|
Map方法總結
元組
與列表同樣,與列表不一樣的是元組能夠包含不一樣類型的元素。元組的值是經過將單個的值包含在圓括號中構成的。
注意:tuple最多支持22個參數
//建立,最多支持22個 val tuple = new Tuple1(1) val tuple2 = Tuple2("zhangsan",2) val tuple3 = Tuple3(1,2,3) val tuple4 = (1,2,3,4) val tuple18 = Tuple18(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18) val tuple22 = new Tuple22(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)
//使用 println(tuple2._1 + "\t"+tuple2._2) val t = Tuple2((1,2),("zhangsan","lisi")) println(t._1._2) |
tuple.productIterator獲得迭代器,進而遍歷
//遍歷 val tupleIterator = tuple22.productIterator while(tupleIterator.hasNext){ println(tupleIterator.next()) } |
注意:swap元素翻轉,只針對二元組
/** * 方法 */ //翻轉,只針對二元組 println(tuple2.swap)
//toString println(tuple3.toString()) |
trait 特性
Scala Trait(特徵) 至關於 Java 的接口,實際上它比接口還功能強大。
與接口不一樣的是,它還能夠定義屬性和方法的實現。
通常狀況下Scala的類能夠繼承多個Trait,從結果來看就是實現了多重繼承。Trait(特徵) 定義的方式與類相似,但它使用的關鍵字是 trait。
注意:
trait Read { val readType = "Read" val gender = "m" def read(name:String){ println(name+" is reading") } }
trait Listen { val listenType = "Listen" val gender = "m" def listen(name:String){ println(name + " is listenning") } }
class Person() extends Read with Listen{ override val gender = "f" }
object test { def main(args: Array[String]): Unit = { val person = new Person() person.read("zhangsan") person.listen("lisi") println(person.listenType) println(person.readType) println(person.gender)
} } |
object Lesson_Trait2 { def main(args: Array[String]): Unit = { val p1 = new Point(1,2) val p2 = new Point(1,3) println(p1.isEqule(p2)) println(p1.isNotEqule(p2)) } }
trait Equle{ def isEqule(x:Any) :Boolean def isNotEqule(x : Any) = { !isEqule(x) } }
class Point(x:Int, y:Int) extends Equle { val xx = x val yy = y
def isEqule(p:Any) = { p.isInstanceOf[Point] && p.asInstanceOf[Point].xx==xx }
} |
模式匹配match
Scala 提供了強大的模式匹配機制,應用也很是普遍。
一個模式匹配包含了一系列備選項,每一個都開始於關鍵字 case。
每一個備選項都包含了一個模式及一到多個表達式。箭頭符號 => 隔開了模式和表達式。
object Lesson_Match { def main(args: Array[String]): Unit = { val tuple = Tuple6(1,2,3f,4,"abc",55d) val tupleIterator = tuple.productIterator while(tupleIterator.hasNext){ matchTest(tupleIterator.next()) }
} /** * 注意點: * 1.模式匹配不只能夠匹配值,還能夠匹配類型 * 2.模式匹配中,若是匹配到對應的類型或值,就再也不繼續往下匹配 * 3.模式匹配中,都匹配不上時,會匹配到 case _ ,至關於default */ def matchTest(x:Any) ={ x match { case x:Int=> println("type is Int") case 1 => println("result is 1") case 2 => println("result is 2") case 3=> println("result is 3") case 4 => println("result is 4") case x:String => println("type is String") // case x :Double => println("type is Double") case _ => println("no match") } }
} |
樣例類(case classes)
使用了case關鍵字的類定義就是樣例類(case classes),樣例類是種特殊的類。實現了類構造參數的getter方法(構造參數默認被聲明爲val),當構造參數是聲明爲var類型的,它將幫你實現setter和getter方法。
case class Person1(name:String,age:Int)
object Lesson_CaseClass { def main(args: Array[String]): Unit = { val p1 = new Person1("zhangsan",10) val p2 = Person1("lisi",20) val p3 = Person1("wangwu",30)
val list = List(p1,p2,p3) list.foreach { x => { x match { case Person1("zhangsan",10) => println("zhangsan") case Person1("lisi",20) => println("lisi") case _ => println("no match") } } }
} } |
Actor Model
Actor Model是用來編寫並行計算或分佈式系統的高層次抽象(相似java中的Thread)讓程序員沒必要爲多線程模式下共享鎖而煩惱,被用在Erlang 語言上, 高可用性99.9999999 % 一年只有31ms 宕機Actors將狀態和行爲封裝在一個輕量的進程/線程中,可是不和其餘Actors分享狀態,每一個Actors有本身的世界觀,當須要和其餘Actors交互時,經過發送事件和消息,發送是異步的,非堵塞的(fire-andforget),發送消息後沒必要等另外Actors回覆,也沒必要暫停,每一個Actors有本身的消息隊列,進來的消息按先來後到排列,這就有很好的併發策略和可伸縮性,能夠創建性能很好的事件驅動系統。
Actor的特徵:
什麼是Akka
Akka 是一個用 Scala 編寫的庫,用於簡化編寫容錯的、高可伸縮性的 Java 和Scala 的 Actor 模型應用,底層實現就是Actor,Akka是一個開發庫和運行環境,能夠用於構建高併發、分佈式、可容錯、事件驅動的基於JVM的應用。使構建高併發的分佈式應用更加容易。
spark1.6版本以前,spark分佈式節點之間的消息傳遞使用的就是Akka,底層也就是actor實現的。1.6以後使用的netty傳輸。
import scala.actors.Actor
class myActor extends Actor{
def act(){ while(true){ receive { case x:String => println("save String ="+ x) case x:Int => println("save Int") case _ => println("save default") } } } }
object Lesson_Actor { def main(args: Array[String]): Unit = {
//建立actor的消息接收和傳遞 val actor =new myActor() //啓動 actor.start() //發送消息寫法 actor ! "i love you !"
} } |
case class Message(actor:Actor,msg:Any)
class Actor1 extends Actor{ def act(){ while(true){ receive{ case msg :Message => { println("i sava msg! = "+ msg.msg)
msg.actor!"i love you too !" } case msg :String => println(msg) case _ => println("default msg!") } } } }
class Actor2(actor :Actor) extends Actor{ actor ! Message(this,"i love you !") def act(){ while(true){ receive{ case msg :String => { if(msg.equals("i love you too !")){ println(msg) actor! "could we have a date !" } } case _ => println("default msg!") } } } }
object Lesson_Actor2 { def main(args: Array[String]): Unit = { val actor1 = new Actor1() actor1.start() val actor2 = new Actor2(actor1) actor2.start() } } |
WordCount
import org.apache.spark.SparkConf import org.apache.spark.SparkContext import org.apache.spark.rdd.RDD import org.apache.spark.rdd.RDD.rddToPairRDDFunctions
object WordCount { def main(args: Array[String]): Unit = { val conf = new SparkConf() conf.setMaster("local").setAppName("WC") val sc = new SparkContext(conf) val lines :RDD[String] = sc.textFile("./words.txt") val word :RDD[String] = lines.flatMap{lines => { lines.split(" ") }} val pairs : RDD[(String,Int)] = word.map{ x => (x,1) } val result = pairs.reduceByKey{(a,b)=> {a+b}} result.sortBy(_._2,false).foreach(println)
//簡化寫法 lines.flatMap { _.split(" ")}.map { (_,1)}.reduceByKey(_+_).foreach(println)
} } |