簡單總結一下scala這門編程語言,希望能讓大家快速入門。
一、scala簡介
介紹:
scala是一門多範式,命令行式編程語言,將面向對象和函數式編程結合在一起並且基於JVM之上的語言。
作者:
scala的作者叫馬丁·奧德斯基,同時也是Java JVM的開發者兼Java泛型的創始人。所以scala是基於java開發的,scala的任務也是基於JVM(虛擬機)基礎之上。
發行時間:
2004年推出第一版scala,然後在2009年推出2.x版本
應用:
底層腳本編寫、spark開發等
學習scala的目的:
1)適合大數據開發
2)語法也比較簡單:對比Java來說,實現同樣的功能,scala的代碼量會更少一點,開發敏捷
3)運行速度快:scala語言表達能力強,一行相當於java的多行代碼,開發快,是靜態編程的語言
4)適合hadoop生態:能融入hadoop生態,可以使用基於spark技術棧,進行Hadoop內的操作,主要還是能無縫對接HDFS
簡單回顧一下java,因爲scala是基於Java開發的,所以scala同樣也可以導入Java的類庫使用:
主要由JDK、JRE、JVM三部分組成:
JDK(Java Development Kit):是 Java語言的軟件開發工具包(SDK)。在JDK的安裝目錄下有一個jre目錄,裏面有兩個文件夾bin和lib,在這裏可以認爲bin裏的就是jvm,lib中則是jvm工作所需要的類庫,而jvm和 lib合起來就稱爲jre。
JRE(Java Runtime Environment,Java運行環境):包含JVM標準實現及Java核心類庫。JRE是Java運行環境,並不是一個開發環境,所以沒有包含任何開發工具(如編譯器和調試器)
JVM(Java Virtual Machine虛擬機):JVM是一種用於計算設備的規範,它是一個虛構出來的計算機,是通過在實際的計算機上仿真模擬各種計算機功能來實現的。
二、聲明變量的方式
val和var
1)val:只能初始化一次,但是可以調用,類似Java中定義的常量final
2)var:同java的變量定義一樣,可隨時賦值修改
注意:
在聲明變量的時候,儘量使用val,因爲聲明的變量在被調用或使用(在網絡傳輸過程中),會發生序列化和反序列化操作,那麼可能會發生數據值被傳錯的情況,造成數據丟失。
三、數據類型
Any:類似Java中的Object,是Scala數據類型中的頂級父類。如果不想寫死一個類型,可以使用頂級父類Any。
基本數據類型:
1)Byte
2)Char
3)Short
4)Int
5)Long
6)Float
7)Double
8)Boolean
注意:首字母都是大寫,每個都相當於Java裏的引用類型,但是沒有Java裏的包裝類型
Scala內部提供了一些加強版類型:
1)RichInt
2)RichDouble
3)RichChar等類型
四、自增寫法
Java中自增可以用++表示,scala沒有這種表達方式,只有:
+=value
如:count+=1
五、scala中的apply函數
apply函數(初始化函數):
這個apply函數其實相當於我們在定義的一些類的時候,有的類需要new,才能創建,但是在scala編程中,爲了簡化使用者難度,有一些操作,是在內部進行初始化,相當於說,使用者不需要再去new類或者對象,而是直接調用。如:
Java中 new Person()
Scala中 Person()
六、if表達式
java和C++中有一個三目運算符 ?:和if表達式表示同樣的意思
而scala的if/else是將java、C++的if/else語法結構和三目運算符結合在一起了
如:x > 0 ? 1 : -1 等價於scala中的 if (x>0) 1 else 0
七、塊表達式和語句終結符 ;
1)在scala語言中不需要語句終結符,默認一行一條語句。
對比:java中需要用;(分號)表示語句的終結。
2)塊表達式:指的是{}中的值,只要被當前這個{}包含的叫塊表達式
八、循環
1)增強型for循環
java例子:
int[] array = {1,2,3,4,5,6};
for (int i : array) {
if (i!=null){
System.out.print(i);
}
}//輸出結果爲:123456
scala例子:
val array = Array(1,2,3,4,5,6)
for (i <- array){
print(i)
}//輸出結果爲:123456
總結:scala中用 <-(左箭頭) 代替了 :(冒號)
2)生成器表達式(scala中之所以叫這個名字是因爲該表達式會基於集合生成單獨的數值,左箭頭<- 操作符用於像列表這樣的集合進行遍歷)
對於數值的遞增遞減問題
java例子:
遞增:for (int i = 0, i < 10, i++){}
遞減:for (int i = 10, i > 0, i--){}
scala例子:
遞增:for (i <- 1 to 10){}
遞減:for (i <- (1 to 10).reverse){}
總結:對於循環來說,scala中不同於java在於scala提供了Range類型取代了java中的數值操作
補充:
Range類型
1. 1 to 10 //表示Int類型的Range,包括區間上限,步長爲1(從1到10)
2. 1 until 10 //表示Int類型的Range,不包括區間上限,步長爲1(從1到9)
3. 1 to 10 by 3 //表示Int類型的Range,不包括區間上限,步長爲3(1、4、7、10)
4. 10 to 1 by -3 //表示Int類型的遞減Range,包括區間下限,步長爲-3(10、7、4、1)
5. 1f to 10.3f by 3.1f// Float類型的Range,步長可以不等於1(1.0、4.1、7.2、10.299999)
3)foreach遍歷
注意:foreach沒有返回值,所以大多時候都不會使用foreach
例子:val array = Array(1,2,3,4,5,6)
array.foreach(x => print(x))
//輸出結果爲:123456
4)循環控制
A)if守衛
例子:for (i <- 0 to 10 if i!=0 if i%2==0) { print(i) }
//輸出結果爲:2 4 6 8 10
B)filter(過濾)等方式實現循環控制
例子:val array = Seq("a","b","c","d","e")
array.filter(_.startsWith("a")).foreach(println)
//輸出結果爲:a
//表示過濾出數組裏每個元素首字母爲“a”的元素,然後遍歷打印
九、scala中函數和方法的定義
1)函數基本語法
val func1 =(參數:類型) => (函數體) //函數分匿名函數和非匿名函數,函數可以作爲參數傳遞
例子:val func1 = (x:Int) => x*2
print(func(2))
//輸出結果爲:4
2)方法基本語法
方法關鍵字def 方法名(方法參數:參數類型): 方法返回值類型=方法體
例子:斐波那契數列(遞歸)方法實現
def fibonacci(n:Int):Int = {
if(n<=2) 1 else fibonacci(n-1)+fibonacci(n-2)
}
3)scala中可以爲函數的參數指定默認值
設置了默認值,調用函數的時候,如果沒有傳參則會使用默認值;如果傳參了,就會取代默認值
十、scala中的高階函數
1)作爲參數的函數
函數格式:val 變量名 = (參數:參數類型) => 函數體
例子:val arr = Array(1,2,3,4,5,6)
val func1 = (x:Int) => x*2
arr.map(func1) //將函數作爲參數傳入map方法中
//輸出結果爲:2 4 6 8 10
2)匿名函數
在scala中你可以不需要給一個函數命名,沒有將函數賦給變量的函數可以稱爲匿名函數
例子1:
arr.map((x:Int) => x*2) //結果同上
例子2:
arr.map(_*2) //結果同上
3)柯里化
概念:指的是把原來一個參數位接受多個參數的函數變換成一個參數位只接受一個參數的函數的過程
非柯里化例子:def add(x:Int,y:Int) =x+y
print(add(1,2))
//輸出結果爲:3
柯里化例子: def add(x:int)(y:Int) =x+y
print(add(1)(2))
//輸出結果爲:3
柯里化風格的特點:
簡化主函數的複雜度,提高主函數的自閉性。提高功能上的可擴張性、靈活性。可以編寫出更加抽象,功能化和高效的函數式代碼。
4)閉包
概念:閉包是一個函數,指函數的返回值依賴於聲明在函數外部的一個變量或多個變量。
即:可以訪問不在當前作用域範圍內的一個函數
例子:val y = 10
val add =(x:Int) =>{x+y}
print(add(5))
//輸出結果爲:15
//其中x爲形參,y爲自由變量,且y不在add函數作用域範圍內
十一、scala中方法使用(舉例部分)
1)flatMap
含義:返回迭代器中的元素
例子: val flatmap =List("apple1 apple2","apple3 apple4")
flatmap.flatMap(_.split(" ")).foreach(x =>print(x+" "))
//結果返回一個對象apple1 apple2 apple3 apple4
擴展:flatMap和map有什麼區別?
先舉個map的例子:
val flatmap =List("apple1 apple2","apple3 apple4")
flatmap.map(_.split(" ")).foreach(x =>print(x+" "))
//結果返回兩個對象
//對象一 apple1 apple2
//對象二 apple3 apple4
總結:我們可以看出
map:會對每一條數據進行指定的操作,然後爲每一條數據返回一個對象
flatMap:相當於集合了map+flatten兩步操作,在map的基礎上還會對每條數據map操作後的結果進行扁平化,類似迭代每個元素然後最終合併成一個對象返回
2)Zip族方法
含義:將傳進來的兩個參數中相應位置上的元素組成一個pair數組。如果其中一個參數元素比較長,那麼多餘的參數會被刪掉
例子:val z1=List("C", "C++", "Java", "Scala")
val z2=List(100, 90, 75, 83)
z1.zip(z2).foreach(x =>print(x+" "))
//結果爲 (C,100) (C++,90) (Java,75) (Scala,83)
3)lazy關鍵字
含義:在Scala中,提供了lazy值的特性,也就是說,如果將一個變量聲明爲lazy,則只有在第一次使用該變量時,變量對應的表達式纔會發生計算,這種特性針對於特別耗時的計算操作比較生效,比如打開文件進行IO,進行網絡IO等。
例子:import scala.io.Source._
lazy val lines = fromFile(本地文件路徑).mkString
4)SortedMap
含義:返回元素按照key的字典排序的映射
例子1:val gredes = SortedMap(("D",90),("E",86),(C",88),("B",78),("A",93))
grades.foreach(x =>print(x+" "))
//輸出結果爲:("A",93)("B",78)("C",88)("D",90)("E",86)
例子2:val gredes = SortedMap(("1",90),("3",86),(2",88),("5",78),("4",93))
grades.foreach(x =>print(x+" "))
//輸出結果爲:("1",90)("2",88)("3",86)("4",93)("5",78)
5)LinkedHashMap
含義:安插入時的順序返回元素
例子:var status=mutable.LinkedHashMap((5,"apple"))
status +=((3,"orange"))
status +=((6,"banana"))
println(status)
//結果:Map(5 -> apple, 3 -> orange, 6 -> banana)
6)ListMap
含義:按插入的相反順序返回元素
例子:var status=mutable.ListMap((1,"a"))
status +=((2,"b")) //結果:Map(2 -> b, 1 -> a)
status +=((3,"c")) //結果:Map(3 -> c, 1 -> a, 2 -> b)
7)scala版的wordcount入門案例
//第一步,導入scala相關IO包
import scala.io.Source._
//第二步,導入本地文件,並轉成字符串類型
val lines:String = fromFile("E://test.txt").mkString
//第三步,將字符串轉成集合類型按規則拆分成單個字符串
val words:List[String] = lines.toList.flatMap(_.split(" "))
//第四步,對words進行map聚合標記,返回一個tuple元組
val tuples:List[String,Int] = words.map((_,1))
//第五步, 按key分組
val group:Map[String,List[String,Int]] = tuples.groupBy(_._1)
//第六步,統計每個key對應value值的長度,即詞頻
val sum:Map[String,Int] = group.mapValues(_.size)
println(sum)
//結果
//Map(suke -> 1, Tom -> 1, Jerry -> 1, beta -> 1, hello -> 4)
未完待續,請關注scala入門篇(二)