scala

 

   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

  eclipse下載scala插件下載shell

解壓下載的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運行報錯:

Scala eclipse 錯誤 -找不到或沒法加載主類

這是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,隱式轉換

隱式轉換函數是指在同一個做用域下面,一個給定輸入類型並自動轉換爲指定返回類型的函數,這個函數和函數名字無關,和入參名字無關,只和入參類型以及返回類型有關。注意是同一個做用域。

  1. 記住隱式轉換函數的同一個scop中不能存在參數和返回值徹底相同的2個implicit函數。
  2. 隱式轉換函數只在乎 輸入類型,返回類型。
/**
  * 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 測試類運行時老是顯示 「沒法加載的主類」

這個是由於類寫在工程源碼路徑以外

推薦書籍:七天七語言

參考材料:廈大數據庫實驗室大數據教程

相關文章
相關標籤/搜索