- scala介紹
- 如何理解函數編程
- scala特點
- scala語法
- 數據類型
- 變量
- 條件表達式
- for循環,while循環
- 方法和函數
方法:簡單方法和複雜方法
函數:函數簽名,複雜函數,高階函數,方法轉化爲函數
- scala的集合框架
- 元組
- 數組
- list
- map
- set
- 結合常用的方法:
- 運算符重載爲方法
- map
- filter
- flatten
- flatMap
- foreach
- storby sortwith sorted
- 交集 差集 並集 去重
- count find
- grouped
- mkString
- To until
-
mapValues
-
Reduce reduceLeft reduceRight
- Fold foldLeft FoldRight
- aggregate
- 案例聯繫
1.wordCount
2.編寫一個方法 getValues(arr:Array[Int],v:Int) 返回數組中小於v 等於 v 大於v的元素個數 要求三個值一起返回
3.數組反轉 兩兩交換 Array(1,2,3,4,5,6)
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
scala簡介:
scala語言特點: 面向對象編程和函數式編程
如何理解函數是編程:
定義好規範,調用的時候,傳遞引用,一些列的函數調用
scala特點:
1.優雅 速度快
2. 語言表達能力強
3.簡易
scala的語法:
數據類型:AnyVal ,AnyRef
AnyVal :
數值類型 : Byte Int Short Long Float Double
非數值類型 : Boolean Unit
注意事項 : 1. 首字母全大寫 全是包裝類型
2.Unit 表示空值 相當於Java中的void 只有一個值 () 小括號
變量 :
String str = “hello tom”;
兩個關鍵字 : val var
Val 修飾的是常量 相當於java中的常量 不可變
Var 修飾的是變量
scala> val c=()
c: Unit = ()
scala> val a=5
a: Int = 5
scala> val a="hehe"
a: String = hehe
scala> val a="true"
a: String = true
scala> val a=true
a: Boolean = true
scala> val name:String="hehe"
name: String = hehe
scala> val name:Int="hehe"
<console>:11: error: type mismatch;
found : String("hehe")
required: Int
val name:Int="hehe"
^
scala> val name="hehe"
name: String = hehe
條件表達式:
If(){}
If(){} else {}
If(){} else if(){} else if(){} else{}
1.條件表達式都有返回值
scala> val result = if(age<25){println("to young")}
to young
result: Unit = ()
2.條件表達式的返回值 如果有多個分支 由每一個分支最後一行決定
scala> val result = if(age<25){println("too yount")}else{age}
too yount
result: AnyVal = ()
- 如果各個分支返回的結果類型不一致 那麼此時 取他們的父類行
3.如果只有一個if 沒有else 那麼此時 else的返回類型是unit
scala> val result = if(age<25){println(age)}
18
result: Unit = ()
4.如果if else的語句 只有一行 可以省略 {} 但是不建議
def main(args: Array[String]): Unit = {
val age = 18
val a = if (age < 18) {
age
} else {
"hehe"
}
println(a)
}
for循環
object TestFor {
def main(args: Array[String]): Unit = {
var arr = Array[Int](1, 2, 3, 4, 5, 6);
//循環 相當於java中的增強for循環
for (a <- arr) {
// println(a)
}
//帶索引的 藉助兩個生成器 1.to(10)
// 1 to 10 1-10
// 1 until 10 1-9
for (i <- 0 to arr.length - 1) {
//println(i + "-----" + arr(i))
}
//帶守衛的for循環
for (i <- arr if (i % 2 == 0)) {
// println(i)
}
//嵌套的for循環
for (i <- 1 to 3) {
for (j <- 1 to 3) {
if (i != j) {
// print(i+" ")
// println(i * 10 + j + " ")
}
}
}
for (i <- 1 to 3; j <- 1 to 3; if (i != j)) {
// println(i * 10 + j + " ")
}
val reslut: Array[Int] = for (a <- arr) yield a * 10
//println(reslut.toBuffer)
//函數式編程的方式來寫 過濾對2取餘等於0的數
arr.filter(t => t % 2 == 0).foreach(println)
arr.map(x => x * 10).foreach(println)
}
while循環
object TestWhile {
def main(args: Array[String]): Unit = {
var i = 0;
var flag = true
while (i < 100 && flag) {
if (i == 5) flag = false
// println(i)
i += 1;
}
var a = 1;
while (true) {
println(a)
}
do {
println(a);
a += 1;
} while (a < 15);
}
方法和函數(重點和難點 )
方法: 代碼的抽取和複用
scala中的方法
Def 方法名稱(參數列表):返回值類型={
方法體的內容
}
def add(a:Int,b:Int):Int={
a+b
}
def add2():Int={
100
}
def add3:Int={
200
}
def add(x:Int*):Int={
x // seq
var sum = 0
for(i<-x){
sum+=i
}
sum
}
//有比上一個方法更簡單的調用
def add1(x:Int*): Int ={
x.sum
}
我們的返回值是可以去掉的 編譯器會自動幫我們推薦 如果方法沒有指定返回值 編譯器可以自動推斷 但是 要加 = 如果不加 = 就意味着返回值爲 Unit
但是有兩種情況必須寫明返回值類型
- 有return 關鍵字的方法 必須要寫明返回值類型
2.遞歸的情況下
方法的標籤
方法名+輸入參數+方法返回參數類型
函數 函數是一等公民
方法 也是一種特殊的函數
函數的簽名
函數的簽名 : 函數的名稱 輸入類型的參數 返回值的類型
//定義一個求和函數 簡單的定義
//返回值由編譯器判斷
val func1 = (x: Int, y: Int) => {
x + y
}
//匿名函數
(x: Int, y: Int) => x + y
def main(args: Array[String]): Unit = {
println(func1(10, 20))
println()
}
複雜的函數 :
Val 函數的名稱:(輸入參數的類型) => 返回值類型 =(輸入參數的引用)=>{
函數體
}
val fun1: (Int, Int) => Int = (x, y) => {
x * y + 10
}
val fun2: (Int, Int) => Double = (x, y) => {
if (x > y) {
x
} else {
y
}
}
def main(args: Array[String]): Unit = {
println(fun1(10, 20))
println(fun2(10, 20))
}
高階函數 :
函數可以做爲方法的參數 和 返回值類型
object FunDemo3 {
val func: (Int, Int) => Double = (x, y) => {
x * y
}
def hehe(x: Int, y: Int, f: (Int, Int) => Double) = {
f(x, y)
}
def main(args: Array[String]): Unit = {
println(hehe(20, 60, func))
}
}
方法 轉換成函數 : 方法名稱 _
方法和函數的總結 :
- 定義方法 def
- 函數 =>
- 函數可以做爲獨立的表達式單獨存在
- 方法必須要調用 不能作爲獨立的表達式存在
- 函數是一等公民 和 類 和對象在一個級別 函數可以作爲方法的返回值 和 參數
- 方法本質上 就是函數的一種
- 方法可以轉換爲函數
Scala的集合框架
scala把集合框架分爲3種
序列 : Seq
集: Set
映射 : Map Iterable
每一個集合都有兩個包 根據包分類
不可變集合 scala.collection.immutable 默認的 不需要導入的
可變集合 scala.collection.mutable.*
重點 : 元組 數組 Map List
元組 非常靈活
如何取數據?._下標
對偶元組: 一種特殊的元組
Val tp = (“name”,age) Map中的每一個元素 都是對偶元組
swap方法 可以將兩個元素進行交換
拉鍊操作 zip zipWithIndex
zip
zipWithIndex
tuple最多方22個元素
數組
可變數組 ArrayBuffer 長度內容都可變 scala.collection.mutable
scala> val ab = ArrayBuffer(1,2)
ab: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2)
scala> val ab1 = new ArrayBuffer[Int]()
ab1: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()
scala> ab1+=2
res3: ab1.type = ArrayBuffer(2)
scala> ab1++=ab
res4: ab1.type = ArrayBuffer(2, 1, 2)
scala> ab1-=2
res5: ab1.type = ArrayBuffer(1, 2)
scala> ab1.insert
<console>:14: error: missing argument list for method insert in trait BufferLike
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `insert _` or `insert(_,_)` instead of `insert`.
ab1.insert
^
scala> ab1.in
indexOf indexOfSlice indexWhere indices init inits insert insertAll intersect
scala> ab1.in
indexOf indexOfSlice indexWhere indices init inits insert insertAll intersect
scala> ab1.in
indexOf indexOfSlice indexWhere indices init inits insert insertAll intersect
scala> ab1.insert(0,111,1111)
scala> ab1
res8: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(111, 1111, 1, 2)
scala> ab1.insert(2,22222)
scala> ab1
res10: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(111, 1111, 22222, 1, 2)
scala> ab1.remove(1)
res11: Int = 1111
scala> ab1
res12: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(111, 22222, 1, 2)
scala> ab1.clear
scala> ab1
res14: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()
scala> ab1.isEmpty
res15: Boolean = true
不可變數組 Array 長度不可變 內部可變 默認的情況
def main(args: Array[String]): Unit = {
//val arr=Array[Int](1,23,4,3,24)
//其實類型可以省略
val arr = Array(1, 23, 4, 3, 24)
//獲得值
//下標重0開始
val age = arr(1)
arr(2) = 45
println(arr(2))
println(age)
//我們可以只初始化他的長度,但是必須指定類型
var arr3 = new Array[Int](4)
}
數組常用方法
scala> ab2.max
res16: Int = 7scala> ab2.min
res17: Int = 1scala> ab2.sum
res19: Int = 28scala> ab2.sorted
res20: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6, 7)
scala> ab2.sorted.reverse
res22: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(7, 6, 5, 4, 3, 2, 1)
List
不可變List 長度 和內容 都不可變 默認的
scala> val list=List[Int](1,2,3,6,54,5)
list: List[Int] = List(1, 2, 3, 6, 54, 5)
scala> val l=List(1,2,3,6,54,5)
l: List[Int] = List(1, 2, 3, 6, 54, 5)
Nil:是一個List
scala> List[Int]()==Nil
res1: Boolean = true//例子------------------------------------
scala> val l=List(1,2,3,6,54,5)
l: List[Int] = List(1, 2, 3, 6, 54, 5)scala> 88::l
res5: List[Int] = List(88, 1, 2, 3, 6, 54, 5)
可變的List ListBuffer 長度和內容都可變 scala.collection.mutable.ListBuffer
scala> import scala.collection.mutable.ListBuffer
import scala.collection.mutable.ListBuffer
scala> val list = ListBuffer(1,2,3)
list: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3)
scala> list+=12
res27: list.type = ListBuffer(1, 2, 3, 12)
scala> list
res28: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 12)
scala> ls2
res29: List[Int] = List(6, 7, 8, 9)
scala> list+=(123,321,333)
res30: list.type = ListBuffer(1, 2, 3, 12, 123, 321, 333)
scala> list
res31: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 12, 123, 321, 333)
scala> list++=List(12,3,43,444)
res32: list.type = ListBuffer(1, 2, 3, 12, 123, 321, 333, 12, 3, 43, 444)
scala> list.insert(0,8888)
scala> list
res34: scala.collection.mutable.ListBuffer[Int] = ListBuffer(8888, 1, 2, 3, 12, 123, 321, 333, 12, 3, 43, 444)
scala> list.remove(1)
res35: Int = 1
scala> list.clear
List使用
scala> l.head
res6: Int = 1scala> l.tail
res7: List[Int] = List(2, 3, 6, 54, 5)scala> l.tail.tail
res8: List[Int] = List(3, 6, 54, 5)scala> l.tail.tail.tail
res9: List[Int] = List(6, 54, 5)
Map
Map中存在的元素 都是對偶元組
Key是惟一的
不可變的Map 默認的
def main(args: Array[String]): Unit = {
val map = Map("xiaoming" -> 20, "yilian" -> 56, "xiaomei" -> 50)
val mao2 = new HashMap[String, Int]()
val map3 = map ++ mao2
//------獲取值
//1.不常用 如果key不存在對應的value 那麼直接報錯
val age1=map("xiaoming")
//2.val age1: Option[Int] = map.get("reba") 返回的是 有 Some 無 : None
val age2=map.get("xiaoming").get
//3.常用
val age3=map.getOrElse("xiaoming",0)
println(age1)
println(age2)
println(age3)
//println(map3)
}
可變的Map scala.collection.mutable.Map 映射 key -v
Set
主要用去重
可變:
scala> val ses = Set[Int](1,2,3,4,4,5,5)
ses: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)
不可變:
scala> import scala.collection.mutable.Set
import scala.collection.mutable.Set
scala> val ms = Set[Int](10)
ms: scala.collection.mutable.Set[Int] = Set(10)
scala> ms+=(11,13)
res0: ms.type = Set(13, 10, 11)
scala> ms++=Set(1,2,3,4)
res1: ms.type = Set(1, 13, 2, 3, 10, 4, 11)
scala> ms --=Set(1)
res2: ms.type = Set(13, 2, 3, 10, 4, 11)
scala> ms.head
res3: Int = 13
scala> ms.tail
res4: scala.collection.mutable.Set[Int] = Set(2, 3, 10, 4, 11)
scala> ms.remove(2)
res5: Boolean = true
scala> ms.foreach(println)
13
3
10
4
11
去重示例
scala> val list = List(11,11,12,12,123,123,333,333)
list: List[Int] = List(11, 11, 12, 12, 123, 123, 333, 333)
scala> val list1=list.toSet
list1: scala.collection.immutable.Set[Int] = Set(11, 12, 123, 333)
scala> list1.toList
res12: List[Int] = List(11, 12, 123, 333)
集合上常用的方法
運算符重載爲方法:,可以變爲空格,可以省略括號
scala> 3+2
res0: Int = 5
scala> 3.+(5)
res1: Int = 8
scala> 1 to 10
res2: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> 1.to(5)
res3: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5)
Map :
1.map就是映射 對集合中的每一個元素執行某一項操作
2.返回值 正常情況下 原來集合是什麼類型 返回什麼類型
3.返回集合的元素的類型 取決於我們函數的返回值類型
val f=(x:Int)=>x*10
def main(args: Array[String]): Unit = {
val lst = List(2,3,4,5)
val lst2: List[Int] = lst.map((t:Int)=>t*10)
val lst3 = lst.map(f)
//可以省略函數裏的參數類型 誰調用的這個map算子 那麼他裏面的數據類型是啥 就是什麼類型
val lst4 = lst.map(x=>x*10)
val fs: List[Boolean] = lst.map(x=>x%2==0)
println(lst4)
/**
* 總結:
* 1.map就是映射 對集合中的每一個元素執行某一項操作
* 2.返回值 正常情況下 原來集合是什麼類型 返回什麼類型
* 3.返回集合的元素的類型 取決於我們函數的返回值類型
*/
}
filter:過濾,過濾出來自己想要的數據
def main(args: Array[String]): Unit = {
val list = List(Array(1,2,3),Array(4,5,6),Array(7,8,9))
val flats: List[Int] = list.flatten
val lst = flats
println(lst.toBuffer)
}
flatten 壓平,將一個數組種的所有數組壓成一集
scala> val ar=List(List(1,2,3),List("hehe","haha"))
ar: List[List[Any]] = List(List(1, 2, 3), List(hehe, haha))
scala> ar.flatten
res4: List[Any] = List(1, 2, 3, hehe, haha)
FlatMap:壓平加切割
scala> val arr = Array("hello spark","hello hadoop")
arr: Array[String] = Array(hello spark, hello hadoop)
scala> val splits = arr.map(str=>str.split(" "))
splits: Array[Array[String]] = Array(Array(hello, spark), Array(hello, hadoop))
scala> splits.flatten
res0: Array[String] = Array(hello, spark, hello, hadoop)
scala> arr.flatMap(x=>x.split(" "))
res1: Array[String] = Array(hello, spark, hello, hadoop)
Foreach 打印一個list,array,map,底層調用的是applay方法
就是對每一個元素執行操作 返回值是Unit
scala> ar.foreach(println)
List(1, 2, 3)
List(hehe, haha)
Sortby sortwith sorted
Sorted: 默認是升序
Sortby : 參數是一個函數 指定排序的規則 默認是升序
Sortwith: 接收兩個參數 兩個參數進行比較
scala> val lst = List(12,1,23,34,2)
lst: List[Int] = List(12, 1, 23, 34, 2)
scala> lst.sorted
res0: List[Int] = List(1, 2, 12, 23, 34)
scala> lst.sortWith((a,b)=>a>b)
res1: List[Int] = List(34, 23, 12, 2, 1)
scala> lst.sortWith((a,b)=>a<b)
res2: List[Int] = List(1, 2, 12, 23, 34)
scala> lst.sortWith((_,_)=>_>_)
<console>:13: error: missing parameter type for expanded function ((x$3, x$4) => x$3.$greater(x$4))
lst.sortWith((_,_)=>_>_)
^
<console>:13: error: missing parameter type for expanded function ((x$3: <error>, x$4) => x$3.$greater(x$4))
lst.sortWith((_,_)=>_>_)
^
scala> lst.sortWith(_>_)
res4: List[Int] = List(34, 23, 12, 2, 1)
交集 差集 並集 去重
並集: union
交集: intersect
差集: diff
去重 : distinct
scala> val arr = Array(1,2,3)
arr: Array[Int] = Array(1, 2, 3)
scala> val arr2 = Array(1,2,5)
arr2: Array[Int] = Array(1, 2, 5)
scala> arr union arr2
res5: Array[Int] = Array(1, 2, 3, 1, 2, 5)
scala> res5.distinct
res6: Array[Int] = Array(1, 2, 3, 5)
scala> arr diff arr2
res7: Array[Int] = Array(3)
scala> arr intersect arr2
res8: Array[Int] = Array(1, 2)
Count 和 find
find 返回滿足條件的第一個元素 Some 沒有則返回none
Count返回滿足條件的所有元素的個數和
object CountAndFindDemo {
def main(args: Array[String]): Unit = {
val lst = List(2,3,4,5)
val counts = lst.count(_>3)
println("xxx"+counts)
//find 返回滿足條件的第一個元素 Some
//filter 返回滿足條件的所有元素
val lst1 = lst.find(_>3)
println(lst1.get)
}
}
Grouped(n:Int) 按照指定元素的個數來分組
val arr = Array(1,2,3,4,5,5,6,6,93,3)
arr.grouped(2)
res9: Iterator[Array[Int]] = non-empty iterator
scala> res14.foreach(arr=>println(arr.toList))
List(1, 2)
List(3, 4)
List(5, 5)
List(6, 6)
mkString:
scala> arr
res16: Array[Int] = Array(1, 2, 3, 4, 5, 5, 6, 6, 93, 3)
scala> arr.mkString
res17: String = 12345566933
scala> arr.mkString("@")
res18: String = 1@2@3@4@5@5@6@6@93@3
To until 其實他們都還可以指定步長
scala> 1 to 10
res19: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> 1.to(10,2)
res20: scala.collection.immutable.Range.Inclusive = Range(1, 3, 5, 7, 9)
scala> 10.to(1,-3)
res21: scala.collection.immutable.Range.Inclusive = Range(10, 7, 4, 1)
mapValues 和 map類似 只不過 mapValues 處理的Map集合中的value值 key保持不變
def main(args: Array[String]): Unit = {
val mp = Map[String,Int]("a"->1001,"b"->1002,"c"->1003)
mp.map(t=>(t._1,t._2*10)).foreach(println)
mp.mapValues(_*10).foreach(println)
}
Reduce reduceLeft reduceRight
Reduce: 元素的歸併 元素的聚合 具體如何聚合 取決於我們的函數
def main(args: Array[String]): Unit = {
val a1 = Array[Int](1,3,4,5)
//求和
val r1 = a1.reduce((a,b)=>a+b)
val r2 = a1.reduce(_*_)
println(r1+","+r2)
val a2 = List("1","2","3")
// a2.reduceLeft()
println(a2.reduce(_+_))
//reduceLeft reduceRight
//reduceLeft 向左歸併 reduceRight 向右歸併
println("=============")
println(a1.reduce(_-_))
println(a1.reduceLeft(_-_))
println(a1.reduceRight(_-_))
}
Fold foldLeft FoldRight
Fold : 帶初始值的歸併 和 reduce相比 一樣 就比他多了一個初始值
foldLeft 從左向右歸併
foleRgith 從右向左歸併
def main(args: Array[String]): Unit = {
val a1 = Array(1,2,3,4,5)
println(a1.fold(10)(_+_))
println(a1.foldLeft(10)(_+_))
println(a1.foldRight(10)(_+_))
println("================")
println(a1.fold(10)(_-_))
println(a1.foldLeft(10)(_-_))
println(a1.foldRight(10)(_-_))
}
Aggregate
Aggregate :聚合
單機版的aggregate 調用的是 fold
第一個函數 : 局部聚合
第二個函數 : 全局聚合
def main(args: Array[String]): Unit = {
val arr = Array(1,2,3,4,4,5)
//在scala中 因爲沒有局部和全局的概念 只會執行第一個函數
val a1 = arr.aggregate(0)(_+_,_*_)
println(a1)
}
案列:
1.wordcount案例
def main(args: Array[String]): Unit = {
val list = List("hello world hello tom", "hello storm hello spark hello spark hello spark hello spark", "hello scala world world world")
val strings = list.flatMap(_.split(" ")).map((_, 1)).groupBy(_._1).mapValues(_.size).toList.sortBy(_._2).reverse.foreach(println)
val strings = list.flatMap(_.split(" ")).map((_, 1)).groupBy(_._1).mapValues(_.foldLeft(0)(_ + _._2)).toList.sortBy(_._2)
val strings = list.flatMap(_.split(" ")).map((_, 1)).groupBy(_._1).mapValues()
val result = list.flatMap(_.split(" ")).map((_, 1)).groupBy(_._1).mapValues(_.map(_._2).sum).toList.sortBy(_._2).reverse.foreach(print)
println(result)
}
2.編寫一個方法 getValues(arr:Array[Int],v:Int) 返回數組中小於v 等於 v 大於v的元素個數 要求三個值一起返回
def getCounts(arr:Array[Int],v:Int):(Int,Int,Int)={
val v1 = arr.count(_ < v)
val v2 = arr.count(_ == v)
val v3 = arr.count(_ > v)
(v1,v2,v3)
}
3.數組反轉 兩兩交換 Array(1,2,3,4,5,6)
def swap(arr:Array[Int]):Array[Int]={
for(i <- 0 to (arr.length-1-1,2 )){
//定義一箇中間變量
val tmp = arr(i)
arr(i) = arr(i+1)
arr(i+1) = tmp
}
arr
}