Scala是一門多範式的編程語言,何謂多範式,就是多種方法編程。面向過程:相似c一個main函數順序流執行;面向對象:java/c# oop;泛型,函數式等。html
1,scala命令安裝異常記錄:java
D:\source\scala-2.12.2\bin>scala Exception in thread "main" java.lang.VerifyError: Uninitialized object exists o backward branch 96 Exception Details: Location: scala/tools/nsc/CompilerCommand.sstring$1(Ljava/lang/String;Lscala/collecti n/immutable/List;I)Lscala/Option; @153: goto Reason: Error exists in the bytecode Bytecode: 0x0000000: 2bb6 02dc 9900 07b2 016a b0bb 0154 591c 0x0000010: ba02 e200 00b2 00c9 b600 cd3a 044e 1904 0x0000020: b200 c9b6 00d1 a600 7d2b b200 d6a6 000b 0x0000030: b200 d63a 09a7 0077 bb00 d859 2bb6 00db 0x0000040: c000 2b3a 0a1c 190a b802 deb2 00d6 b700 0x0000050: e83a 0519 053a 062b b600 ebc0 0050 3a07 0x0000060: 1907 b200 d6a5 0037 bb00 d859 1907 b600 0x0000070: dbc0 002b 3a0a 1c19 0ab8 02de b200 d6b7 0x0000080: 00e8 3a08 1906 1908 b600 ef19 083a 0619 0x0000090: 07b6 00eb c000 503a 07a7 ffc7 1905 3a09 0x00000a0: a700 0c2b 2d19 04b8 00f5 3a09 1909 c000 0x00000b0: 502a b602 e613 02e8 b602 e9b7 0159 b0 Stackmap Table: same_frame(@11) full_frame(@56,{Object[#118],Object[#80],Integer,Object[#333],Object[#335]} {Uninitialized[#11],Uninitialized[#11]}) full_frame(@96,{Object[#118],Object[#80],Integer,Object[#333],Object[#335], bject[#216],Object[#216],Object[#80],Top,Top,Object[#43]},{Uninitialized[#11],U initialized[#11]}) full_frame(@156,{Object[#118],Object[#80],Integer,Object[#333],Object[#335] Object[#216],Object[#216],Object[#80],Top,Top,Object[#43]},{Uninitialized[#11], ninitialized[#11]}) full_frame(@163,{Object[#118],Object[#80],Integer,Object[#333],Object[#335] ,{Uninitialized[#11],Uninitialized[#11]}) full_frame(@172,{Object[#118],Object[#80],Integer,Object[#333],Object[#335] Top,Top,Top,Top,Object[#4]},{Uninitialized[#11],Uninitialized[#11]}) at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:41 at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:104) at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
緣由系scala對jdk安裝包要求,因此換舊版本scala解決git
D:\ProgramFiles\scala\bin>scala Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_20). Type in expressions for evaluation. Or try :help.
2,scala,eclipse插件安裝:github
解壓下載的scala插件,在eclipse-install software中選中scala解壓路徑,逐步安裝。數據庫
安裝過程還會下載相關依賴包,網絡不能斷express
3, scala的repl環境:編程
REPL — 交互式解釋器環境。
R(read)、E(evaluate)、P(print)、L(loop)json
能夠在scala shell環境下執行外部scalc命令c#
固然,文件名也能夠是Test.txt,只是一種加載外部命令的方式而已。
5,scala運行報錯:
這是eclipse系統一個bug
scala和java的區別:
1,java和scala都從main函數開始:
scala代碼
def main(args: Array[String]): Unit = { }
java代碼
public static void main(String[] args) { }
2,查看scala安裝包,可知scala依賴scalajar包,運行在jvm上,能夠從交互,腳本的方式運行;
3,scala文件自己經過scalac生成java class類,寫過測試類試試
object Test { def main(args: Array[String]): Unit = { print("aaa"); } }
生成Test$.class和Test.class文件;
直接運行java Test報錯,須要scala依賴,添加依賴之後
ok.爲何要用scala,由於scala和spark關係,更直接的說,spark由scala寫,spark在大數據的優秀性能,因此用scala。估計是由於java自己的冗餘問題比較多。
4,fold,左摺疊和右摺疊
var map1 = Map(1 -> "one", 2 -> "two", 3 -> "three", 4 -> "too") println(map1) var newDs = map1.map(_._2) print(newDs)
運行結果:
Map(1 -> one, 2 -> two, 3 -> three, 4 -> too) List(one, two, three, too)
json打印
println(compact(render(str)))
5,scala大小寫敏感;
6,scala具備類型判斷能力,行末的;是可選的:
java String 申明
String str = "aaa";
scala String 申明
val str = "aaa"
7,scala的基礎數據類型:Byte,char,Short,Int,Long,Float,Bdouble,Boolean。
和java不一樣的是,scala的基礎數據類型都是類,估計就是在java的基礎上再封裝一層;
8,操做符:
在Scala中,可使用加(+)、減(-) 、乘(*) 、除(/) 、餘數(%)等操做符,並且,這些操做符就是方法。例如,5 + 3和(5).+(3)是等價的,也就是說:
a 方法 b 等價於 a.方法(b)
前者是後者的簡寫形式,這裏的+是方法名,是Int類中的一個方法。
val sum = 1+2
val sum = (1).+2
.+表明的是對象(1)執行的+方法
9,幾個scala自定義的語法
to、until、by
10,import ×改成_
由於自動判斷類型,因此import變得有點智能,
一樣是定義map,在import可變map後, university就變成可變值了
11,scala返回值,
對於函數最後一個變量的值,便是返回值,因此看林子雨老師的教程中有寫道
可是,有一點與Java不一樣的是,Scala中的if表達式的值能夠賦值給變量,好比:
val x = 6 val a = if (x>0) 1 else -1
上述代碼執行結束後,a的值爲1。
緣由是最後一個值是1,若是x值是-5,a的值就是-1;
不墨跡,直接驗證下
12,生成器 <- 、守衛
for (變量<-表達式) 語句塊
for (i <- 1 to 5) println(i)
在上面語句中,i不須要提早進行變量聲明,能夠在for語句括號中的表達式中直接使用。語句中,「<-」表示,以前的i要遍歷後面1到5的全部值。
可是,有時候,咱們可能不但願打印出全部的結果,咱們可能但願過濾出一些知足制定條件的結果,這個時候,就須要使用到稱爲「守衛(guard)」的表達式。好比,咱們只但願輸出1到5之中的全部偶數,能夠採用如下語句:
for (i <- 1 to 5 if i%2==0) println(i)
生成器多開
for (i <- 1 to 5; j <- 1 to 3) println(i*j)
運行上述代碼後獲得以下執行結果:
1 2 3 2 4 6 3 6 9 4 8 12 5 10 15
也能夠給每一個生成器都添加一個「守衛」,以下:
for (i <- 1 to 5 if i%2==0; j <- 1 to 3 if j!=i) println(i*j)
運行上述代碼後獲得以下執行結果:
2 6 4 8 12
13,數組引用,從【】轉變爲(),Martin Odersky真是好無聊
數組申明和定義
val myStrArr = new Array[String](3) //聲明一個長度爲3的字符串數組,每一個數組元素初始化爲null myStrArr(0) = "BigData" myStrArr(1) = "Hadoop" myStrArr(2) = "Spark" for (i <- 0 to 2) println(myStrArr(i))
val intValueArr = Array(12,45,33) val myStrArr = Array("BigData","Hadoop","Spark")
列表申明和定義:
val intList = List(1,2,3)
val intList = 3::2::1::Nil
list方法:sum
14,元組tuple
這個數據結構定義的挺有意思,讓不一樣數據類型元素排成隊;
元組的蒂聲明和訪問
15,無參方法甚至連括號均可以省了
16,單例伴生對象:
/* 文件名:Marker.scala * author:菜鳥教程 * url:www.runoob.com */ // 私有構造方法 class Marker private(val color:String) { println("建立" + this) override def toString(): String = "顏色標記:"+ color } // 伴生對象,與類共享名字,能夠訪問類的私有屬性和方法 object Marker{ private val markers: Map[String, Marker] = Map( "red" -> new Marker("red"), "blue" -> new Marker("blue"), "green" -> new Marker("green") ) def apply(color:String) = { if(markers.contains(color)) markers(color) else null } def getMarker(color:String) = { if(markers.contains(color)) markers(color) else null } def main(args: Array[String]) { println(Marker("red")) // 單例函數調用,省略了.(點)符號 println(Marker getMarker "blue") } }
// 單例函數調用,省略了.(點)符號 println(Marker getMarker "blue")
編譯後生成的Marker。class文件中,class Marker和 object Marker自動合成一個Marker class,
其中,class是動態方法和動態類;object是靜態方法和靜態類;
14.apply方法和update方法;
package com.yirong.basin.etl class TestApplyClassAndObject { } class ApplyTest{ def apply() = println("apply method in class is called!") def greetingOfClass: Unit ={ println("Greeting method in class is called.") } } object ApplyTest{ def apply() = { println("apply method in object is called") new ApplyTest() } } object TestApplyClassAndObject{ def main (args: Array[String]) { val a = ApplyTest() //這裏沒有用new,會調用伴生對象中的apply方法 a.greetingOfClass a() // 這裏會調用伴生類中的apply方法 } }
result:
apply method in object is called Greeting method in class is called. apply method in class is called!
15,lamda表達式
s => s.toUpperCase
(參數) => 表達式 //若是參數只有一個,參數的圓括號能夠省略
能夠看出,Lamda表達式其實是一種匿名函數,大大簡化代碼編寫工做。s => s.toUpperCase,它的含義是,對於輸入s,都都執行s.toUpperCase操做。
16,集合操做符
map/flatmap,reduce,
map操做是針對集合的典型變換操做,它將某個函數應用到集合中的每一個元素,併產生一個結果集合。
好比,給定一個字符串列表,咱們能夠經過map操做對列表的中每一個字符串進行變換,讓每一個字符串都變成大寫字母,這樣變換後就能夠獲得一個新的集合。下面咱們在Scala命令解釋器中,演示這個過程:
scala> val books = List("Hadoop", "Hive", "HDFS") books: List[String] = List(Hadoop, Hive, HDFS) scala> books.map(s => s.toUpperCase) res0: List[String] = List(HADOOP, HIVE, HDFS)
flatMap是map的一種擴展。在flatMap中,咱們會傳入一個函數,該函數對每一個輸入都會返回一個集合(而不是一個元素),而後,flatMap把生成的多個集合「拍扁」成爲一個集合。
scala> val books = List("Hadoop","Hive","HDFS") books: List[String] = List(Hadoop, Hive, HDFS) scala> books flatMap (s => s.toList) res0: List[Char] = List(H, a, o, o, p, H, i, v, e, H, D, F, S)
reduce
在Scala中,咱們可使用reduce這種二元操做對集合中的元素進行歸約。
reduce包含reduceLeft和reduceRight兩種操做,前者從集合的頭部開始操做,後者從集合的尾部開始操做。
fold和reduce相似,
摺疊(fold)操做和reduce(歸約)操做比較相似。fold操做須要從一個初始的「種子」值開始,並以該值做爲上下文,處理集合中的每一個元素。
從本質上說,fold函數將一種格式的輸入數據轉化成另一種格式返回。fold, foldLeft和foldRight這三個函數除了有一點點不一樣外,作的事情差很少。我將在下文解釋它們的共同點並解釋它們的不一樣點。
我將從一個簡單的例子開始,用fold計算一系列整型的和。
val numbers = List(5, 4, 8, 6, 2) numbers.fold(0) { (z, i) => z + i } // result = 25
List中的fold方法須要輸入兩個參數:初始值以及一個函數。輸入的函數也須要輸入兩個參數:累加值和當前item的索引。那麼上面的代碼片斷髮生了什麼事?
代碼開始運行的時候,初始值0做爲第一個參數傳進到fold函數中,list中的第一個item做爲第二個參數傳進fold函數中。
一、fold函數開始對傳進的兩個參數進行計算,在本例中,僅僅是作加法計算,而後返回計算的值;
二、Fold函數而後將上一步返回的值做爲輸入函數的第一個參數,而且把list中的下一個item做爲第二個參數傳進繼續計算,一樣返回計算的值;
三、第2步將重複計算,直到list中的全部元素都被遍歷以後,返回最後的計算值,整個過程結束;
四、這雖然是一個簡單的例子,讓咱們來看看一些比較有用的東西。早在後面將會介紹foldLeft函數,並解釋它和fold之間的區別,目前,你只須要想象foldLeft函數和fold函數運行過程同樣。
下面咱們在Scala解釋器中運行代碼。
scala> val list = List(1,2,3,4,5) list: List[Int] = List(1, 2, 3, 4, 5) scala> list.fold(10)(_*_) res0: Int = 1200
能夠看出,fold函數實現了對list中全部元素的累乘操做。fold函數須要兩個參數,一個參數是初始種子值,這裏是10,另外一個參數是用於計算結果的累計函數,這裏是累乘。執行list.fold(10)(*)時,首先把初始值拿去和list中的第一個值1作乘法操做,獲得累乘值10,而後再拿這個累乘值10去和list中的第2個值2作乘法操做,獲得累乘值20,依此類推,一直獲得最終的累乘結果1200。
fold有兩個變體:foldLeft()和foldRight(),其中,foldLeft(),第一個參數爲累計值,集合遍歷的方向是從左到右。foldRight(),第二個參數爲累計值,集合遍歷的方向是從右到左。對於fold()自身而言,遍歷的順序是未定義的,不過,通常都是從左到右遍歷。
??
困擾了半天,終於明白了
對應的摺疊符號
https://twitter.github.io/scala_school/zh_cn/collections.html#fold
8,本機spark安裝:http://blog.csdn.net/u011513853/article/details/52865076
必定要在C盤運行該命令: F:\Program Files\hadoop\bin\winutils.exe chmod 777 /tmp/Hive
eclipse跑spark須要設置系統屬性:
System.setProperty("hadoop.home.dir","D:/hadoop-2.6.4");
eclipse添加hadoop插件,下載地址
9,隱式轉換
隱式轉換函數是指在同一個做用域下面,一個給定輸入類型並自動轉換爲指定返回類型的函數,這個函數和函數名字無關,和入參名字無關,只和入參類型以及返回類型有關。注意是同一個做用域。
/** * Created by skanda on 2017/8/21. */ object ImplicitDemo { def display(input:String):Unit = println(input) implicit def aaa(ccc:Int):String = ccc.toString implicit def aaa(ccc:Boolean):String = if(ccc) "true" else "false" // implicit def booleanTypeConvertor(input:Boolean):String = if(input) "true" else "false" def main(args: Array[String]): Unit = { display("1212") display(12) display(true) } }
10,模式匹配
11,json4s
12,開發過程出現的異常
12.1
正常的庫沒辦法導入,庫由pom.xml導入,懷疑是maven的問題,從新設置下maven便可
12.2,scala sdk設置
每次新建工程都要重複設置,在other setting裏面設置default setting便可。
12.3,新建一個scala 測試類運行時老是顯示 「沒法加載的主類」
這個是由於類寫在工程源碼路徑以外
推薦書籍:七天七語言
參考材料:廈大數據庫實驗室大數據教程