Scala字符串
- String
- StringBuilder 可變
- string操作方法舉例
比較:equals
比較忽略大小寫:equalsIgnoreCase
indexOf:如果字符串中有傳入的assci碼對應的值,返回下標
val str = "abcd"
val str1 = "ABCD"
println(str.indexOf(97))
println(str.indexOf("b"))
println(str==str1)
Scala數組
- 創建數組
/**
* 創建數組兩種方式: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
- 遍歷兩種方式:
// 遍歷兩種方式
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()
}
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)
}
- 可變長數組
val arr = ArrayBuffer[String]("a","b","c")
arr.append("hello","scala")//添加多個元素
arr.+=("end")//在最後追加元素
arr.+=:("start")//在開頭添加元素
arr.foreach(println)
Scala集合
- List
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}
val value = list1.count { x => x>3 }//count
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 }
//可變長list
val listBuffer: ListBuffer[Int] = ListBuffer[Int](1,2,3,4,5)
listBuffer.append(6,7,8,9)//追加元素
listBuffer.+=(10)//在後面追加元素
listBuffer.+=:(100)//在開頭加入元素
listBuffer.foreach(println)
- set
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("****")
set1.toArray.foreach{println}//轉成數組,list
println("****")
set1.toList.foreach{println}
println(set1.mkString) //mkString
println(set1.mkString("\t"))
//可變長
import scala.collection.mutable.Set
val set = Set[Int](1,2,3,4,5)
set.add(100)
set.+=(200)
set.+=(1,210,300)
set.foreach(println)
- map
map創建
//注意:創建map時,相同的key被後面的相同的key頂替掉,只保留一個
val map = Map(
"1" -> "bjsxt",
2 -> "shsxt",
(3,"xasxt")
)
獲取map的值
//map.get(100).getOrElse(“no value”):如果map中沒有對應項,賦值爲getOrElse傳的值。
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中的方法舉例
filter:過濾,留下符合條件的記錄
count:統計符合條件的記錄數
contains:map中是否包含某個key
exist:符合條件的記錄存在不存在
//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")
}))
- 元組
元組定義:與列表一樣,與列表不同的是元組可以包含不同類型的元素。元組的值是通過將單個的值包含在圓括號中構成的。
//創建,最多支持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)
//遍歷
val tupleIterator = tuple22.productIterator
while(tupleIterator.hasNext){
println(tupleIterator.next())
}
//方法
println(tuple2.swap)//翻轉,只針對二元組
//toString
println(tuple3.toString())
- trait 特性
概念理解:Scala Trait(特徵) 相當於 Java 的接口,實際上它比接口還功能強大。
與接口不同的是,它還可以定義屬性和方法的實現。
一般情況下Scala的類可以繼承多個Trait,從結果來看就是實現了多重繼承。Trait(特徵) 定義的方式與類類似,但它使用的關鍵字是 trait。
舉例:trait中帶屬性帶方法實現
//注意:繼承的多個trait中如果有同名的方法和屬性,必須要在類中使用“override”重新定義。
//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)
}
舉例:trait中帶方法不實現
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")
}
}
}
- 偏函數
如果一個方法中沒有match 只有case,這個函數可以定義成PartialFunction偏函數。偏函數定義時,不能使用括號傳參,默認定義PartialFunction中傳入一個值,匹配上了對應的case,返回一個值。
object Lesson_PartialFunction {
def MyTest : PartialFunction[String,String] = {
case "scala" =>{"scala"}
case "hello"=>{"hello"}
case _=> {"no match ..."}
}
def main(args: Array[String]): Unit = {
println(MyTest("scala"))
}
}
- 樣例類(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")
}
} }
}
}
- 隱式轉換
隱式轉換是在Scala編譯器進行類型匹配時,如果找不到合適的類型,那麼隱式轉換會讓編譯器在作用範圍內自動推導出來合適的類型。
隱式值與隱式參數
隱式值是指在定義參數時前面加上implicit。隱式參數是指在定義方法時,方法中的部分參數是由implicit修飾【必須使用柯里化的方式,將隱式參數寫在後面的括號中】。隱式轉換作用就是:當調用方法時,不必手動傳入方法中的隱式參數,Scala會自動在作用域範圍內尋找隱式值自動傳入。
隱式值和隱式參數注意:
1). 同類型的參數的隱式值只能在作用域內出現一次,同一個作用域內不能定義多個類型一樣的隱式值。
2). implicit 關鍵字必須放在隱式參數定義的開頭
3). 一個方法只有一個參數是隱式轉換參數時,那麼可以直接定義implicit關鍵字修飾的參數,調用時直接創建類型不傳入參數即可。
4). 一個方法如果有多個參數,要實現部分參數的隱式轉換,必須使用柯里化這種方式,隱式關鍵字出現在後面,只能出現一次.
隱式轉換函數
隱式轉換函數是使用關鍵字implicit修飾的方法。當Scala運行時,假設如果A類型變量調用了method()這個方法,發現A類型的變量沒有method()方法,而B類型有此method()方法,會在作用域中尋找有沒有隱式轉換函數將A類型轉換成B類型,如果有隱式轉換函數,那麼A類型就可以調用method()這個方法。
隱式轉換函數注意:隱式轉換函數只與函數的參數類型和返回類型有關,與函數名稱無關,所以作用域內不能有相同的參數類型和返回類型的不同名稱隱式轉換函數。
lass Animal(name:String){
def canFly(): Unit ={
println(s"$name can fly...")
}
}
class Rabbit(xname:String){
val name = xname
}
object Lesson_ImplicitFunction {
implicit def rabbitToAnimal(rabbit:Rabbit):Animal = {
new Animal(rabbit.name)
}
def main(args: Array[String]): Unit = {
val rabbit = new Rabbit("RABBIT")
rabbit.canFly()
}
- Actor Model
概念理解:
Actor Model是用來編寫並行計算或分佈式系統的高層次抽象(類似java中的Thread)讓程序員不必爲多線程模式下共享鎖而煩惱,被用在Erlang 語言上, 高可用性99.9999999 % 一年只有31ms 宕機Actors將狀態和行爲封裝在一個輕量的進程/線程中,但是不和其他Actors分享狀態,每個Actors有自己的世界觀,當需要和其他Actors交互時,通過發送事件和消息,發送是異步的,非堵塞的(fire-andforget),發送消息後不必等另外Actors回覆,也不必暫停,每個Actors有自己的消息隊列,進來的消息按先來後到排列,這就有很好的併發策略和可伸縮性,可以建立性能很好的事件驅動系統。
Actor的特徵:
- ActorModel是消息傳遞模型,基本特徵就是消息傳遞
- 消息發送是異步的,非阻塞的
- 消息一旦發送成功,不能修改
- Actor之間傳遞時,自己決定決定去檢查消息,而不是一直等待,是異步非阻塞的
什麼是Akka
Akka 是一個用 Scala 編寫的庫,用於簡化編寫容錯的、高可伸縮性的 Java 和Scala 的 Actor 模型應用,底層實現就是Actor,Akka是一個開發庫和運行環境,可以用於構建高併發、分佈式、可容錯、事件驅動的基於JVM的應用。使構建高併發的分佈式應用更加容易。
spark1.6版本之前,spark分佈式節點之間的消息傳遞使用的就是Akka,底層也就是actor實現的。1.6之後使用的netty傳輸。
//Actor簡單例子發送接收消息
import scala.actors.Actor
class myActor extends Actor{
def act(){
while(true){
receive {
case x:String => println("get String ="+ x)
case x:Int => println("get Int")
case _ => println("get default")
}
}
}
}
object Lesson_Actor {
def main(args: Array[String]): Unit = {
//創建actor的消息接收和傳遞
val actor =new myActor()
//啓動
actor.start()
//發送消息寫法
actor ! "i love you !"
}
}
//Actor與Actor之間通信
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)
}
}