偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Scala精華之處就在這里,拿去,面試也不怕

云計(jì)算 虛擬化
Scala作為一門面向?qū)ο蟮暮瘮?shù)式編程語(yǔ)言,把面向?qū)ο缶幊膛c函數(shù)式編程結(jié)合起來(lái),使得代碼更簡(jiǎn)潔高效易于理解。這就是Scala得到青睞的初衷。

[[427956]]

本文轉(zhuǎn)載自微信公眾號(hào)「大數(shù)據(jù)左右手」,作者左右 。轉(zhuǎn)載本文請(qǐng)聯(lián)系大數(shù)據(jù)左右手公眾號(hào)。

前言

Scala作為一門面向?qū)ο蟮暮瘮?shù)式編程語(yǔ)言,把面向?qū)ο缶幊膛c函數(shù)式編程結(jié)合起來(lái),使得代碼更簡(jiǎn)潔高效易于理解。這就是Scala得到青睞的初衷。

Scala作為一門JVM的語(yǔ)言,大數(shù)據(jù)生態(tài)的大部分組件都是Java語(yǔ)言開發(fā)的,而Scala可以與Java無(wú)縫混編,因此可以很好地融合到大數(shù)據(jù)生態(tài)圈。

主要內(nèi)容

一些基礎(chǔ)東西不再羅列,比如開發(fā)環(huán)境,循環(huán),異常,泛型等等,本篇只介紹獨(dú)到,特殊的精華地方,注重概念理解與用法。

1.變量和數(shù)據(jù)類型

2.函數(shù)式編程

(a)高階函數(shù)

(b)匿名函數(shù)

(c)閉包

(d)函數(shù)柯里化

3.面向?qū)ο?/strong>

(a)類與對(duì)象

(b)伴生對(duì)象

(c)特質(zhì)

4.模式匹配

5.隱式轉(zhuǎn)換

變量和數(shù)據(jù)類型

變量(var聲明變量,val聲明常量)

var 修飾的變量可改變

val 修飾的變量不可改變

但真的如此嗎?

對(duì)于以下的定義

  1. class A(a: Int) { 
  2.   var value = a 
  3.  
  4. class B(b: Int) { 
  5.   val value = new A(b) 

效果測(cè)試

  1. val x = new B(1) 
  2.  
  3. x = new B(1) // 錯(cuò)誤,因?yàn)?nbsp;x 為 val 修飾的,引用不可改變 
  4. x.value = new A(1) // 錯(cuò)誤,因?yàn)?nbsp;x.value 為 val 修飾的,引用不可改變 
  5.  
  6. x.value.value = 1 // 正確,x.value.value 為var 修飾的,可以重新賦值 

事實(shí)上,var 修飾的對(duì)象引用可以改變,val 修飾的則不可改變,但對(duì)象的狀態(tài)卻是可以改變的。

可變與不可變的理解

我們知道scala中的List是不可變的,Map是可變和不可變的。觀察下面的例子

var可變和List不可變的組合

  1. var list = List("左","右"
  2.  
  3. list += "手" 

理解就是

var list指向的對(duì)象是 List("左","右")

后面修改list的指向,因?yàn)槭强勺兊膙ar修飾,list又可以指向新的 List("左","右","手")

如果是以下(會(huì)報(bào)錯(cuò)的)

  1. val list = List("左","右"
  2.  
  3. list += "手" 

val var與Map可變和不可變

  1. var map = Map( 
  2.       "左" -> 1, 
  3.       "右" ->1, 
  4.     ) 
  5. map+=("手"->1) 
  1. val map=scala.collection.mutable.Map( 
  2.   "左" -> 1, 
  3.   "右" ->1, 
  4.  
  5. map+=("手"->1) 

理解

不可變的Map在添加元素的時(shí)候,原來(lái)的Map不變,生成一個(gè)新的Map來(lái)保存原來(lái)的map+添加的元素。

可變的Map在添加元素的時(shí)候,并不用新生成一個(gè)Map,而是直接將元素添加到原來(lái)的Map中。

val不可變的只是指針,跟對(duì)象map沒(méi)有關(guān)系。

數(shù)據(jù)類型

數(shù)據(jù)類型 描述
Byte 8位有符號(hào)補(bǔ)碼整數(shù)。數(shù)值區(qū)間為 -128 到 127
Short 16位有符號(hào)補(bǔ)碼整數(shù)。數(shù)值區(qū)間為 -32768 到 32767
Int 32位有符號(hào)補(bǔ)碼整數(shù)。數(shù)值區(qū)間為 -2147483648 到 2147483647
Long 64位有符號(hào)補(bǔ)碼整數(shù)。數(shù)值區(qū)間為 -9223372036854775808 到 9223372036854775807
Float 32 位, IEEE 754 標(biāo)準(zhǔn)的單精度浮點(diǎn)數(shù)
Double 64 位 IEEE 754 標(biāo)準(zhǔn)的雙精度浮點(diǎn)數(shù)
Char 16位無(wú)符號(hào)Unicode字符, 區(qū)間值為 U+0000 到 U+FFFF
String 字符序列
Boolean true或false
Unit 表示無(wú)值,和其他語(yǔ)言中void等同。用作不返回任何結(jié)果的方法的結(jié)果類型。Unit只有一個(gè)實(shí)例值,寫成()。
Null null 或空引用
Nothing Nothing類型在Scala的類層級(jí)的最底端;它是任何其他類型的子類型。
Any Any是所有其他類的超類
AnyRef AnyRef類是Scala里所有引用類(reference class)的基類

函數(shù)式編程

高階函數(shù)

高階函數(shù)是指使用其他函數(shù)作為參數(shù)、或者返回一個(gè)函數(shù)作為結(jié)果的函數(shù)。在Scala中函數(shù)是"一等公民"。

簡(jiǎn)單例子

  1. val list=List(1,2,3,4) 
  2.  
  3. val function= (x:Int) => x*2 
  4.  
  5. val value=list.map(function

方法為函數(shù)

  1. def main(args: Array[String]): Unit = { 
  2.     val list=List(1,2,3,4) 
  3.     val value=list.map(function
  4.  
  5. def function   (x:Int)=x*2 

返回函數(shù)的函數(shù)

  1. def calculate(symbol:String): (String,String)=>String ={ 
  2.     symbol match { 
  3.       case "拼接方式1" => (a:String,b:String)=> s"拼接方式1:$a , $b" 
  4.       case "拼接方式2" => (a:String,b:String)=> s"拼接方式2: $b , $a" 
  5.     } 
  6.   } 
  1. val function: (String, String) => String = calculate("拼接方式2"
  2.  
  3. println(function("大數(shù)據(jù)""左右手")) 

匿名函數(shù)

Scala 中定義匿名函數(shù)的語(yǔ)法很簡(jiǎn)單,箭頭左邊是參數(shù)列表,右邊是函數(shù)體。

使用匿名函數(shù)后,我們的代碼變得更簡(jiǎn)潔了。

  1. var inc = (x:Int) => x+1 
  2.  
  3. var x = inc(7)-1 

也可無(wú)參數(shù)

  1. var user = () => println("大數(shù)據(jù)左右手")  

閉包

閉包是一個(gè)函數(shù),返回值依賴于聲明在函數(shù)外部的一個(gè)或多個(gè)變量。

閉包通常來(lái)講可以簡(jiǎn)單的認(rèn)為是可以訪問(wèn)一個(gè)函數(shù)里面局部變量的另外一個(gè)函數(shù)。

簡(jiǎn)單理解就是:函數(shù)內(nèi)部的變量不在其作用域時(shí),仍然可以從外部進(jìn)行訪問(wèn)。

  1. val function= (x:Int) => x*2 

閉包的實(shí)質(zhì)就是代碼與用到的非局部變量的混合

閉包 = 代碼 + 用到的非局部變量

  1. val fact=2 
  2. val function= (x:Int) => x*fact 

函數(shù)柯里化

柯里化指的是將原來(lái)接受兩個(gè)參數(shù)的函數(shù)變成新的接受一個(gè)參數(shù)的函數(shù)的過(guò)程。新的函數(shù)返回一個(gè)以原有第二個(gè)參數(shù)為參數(shù)的函數(shù)。

先定義一個(gè)簡(jiǎn)單的

  1. def add(x:Int,y:Int)=x+y 
  2.  
  3. 使用 
  4.  
  5. add(1,2) 

函數(shù)變形(這種方式就叫柯里化)

  1. def add(x:Int,y:Int)=x+y 
  2.  
  3. 使用 
  4.  
  5. add(1,2) 

實(shí)現(xiàn)過(guò)程

add(1)(2) 實(shí)際上是依次調(diào)用兩個(gè)普通函數(shù)(非柯里化函數(shù))

第一次調(diào)用使用一個(gè)參數(shù) x,返回一個(gè)函數(shù)類型的值。

第二次使用參數(shù)y調(diào)用這個(gè)函數(shù)類型的值。

  1. 接收一個(gè)x為參數(shù),返回一個(gè)匿名函數(shù) 
  2.  
  3. 接收一個(gè)Int型參數(shù)y,函數(shù)體為x+y。 
  4.  
  5. def add(x:Int)=(y:Int)=>x+y 
  6.  
  7. (1) 
  8. val result = add(1)  // result= (y:Int)=>1+y 
  9.  
  10. (2) 
  11. val sum = result(2) 
  12.  
  13. (3) 
  14. sum=3 

面向?qū)ο?/h3>

類和對(duì)象

類是對(duì)象的抽象,而對(duì)象是類的具體實(shí)例。類是抽象的,不占用內(nèi)存,而對(duì)象是具體的,占用存儲(chǔ)空間。類是用于創(chuàng)建對(duì)象的藍(lán)圖,它是一個(gè)定義包括在特定類型的對(duì)象中的方法和變量的軟件模板。

類可以帶有類參數(shù)

類參數(shù)可以直接在類的主體中使用。類參數(shù)同樣可以使用var作前綴,還可以使用private、protected、override修飾。scala編譯器會(huì)收集類參數(shù)并創(chuàng)造出帶同樣的參數(shù)的類的主構(gòu)造器。,并將類內(nèi)部任何既不是字段也不是方法定義的代碼編譯至主構(gòu)造器中。

  1. class Test(val a: Int, val b: Int) { 
  2.     //  

樣例類

case class一般被翻譯成樣例類,它是一種特殊的類,能夠被優(yōu)化以用于模式匹配。

當(dāng)一個(gè)類被聲名為case class的時(shí)候。具有以下功能:

  1. 構(gòu)造器中的參數(shù)如果不被聲明為var的話,它默認(rèn)的是val類型的。
  2. 自動(dòng)創(chuàng)建伴生對(duì)象,同時(shí)在里面給我們實(shí)現(xiàn)子apply方法,使我們?cè)谑褂玫臅r(shí)候可以不直接使用new創(chuàng)建對(duì)象。
  3. 伴生對(duì)象中同樣會(huì)幫我們實(shí)現(xiàn)unapply方法,從而可以將case class應(yīng)用于模式匹配。
  4. 實(shí)現(xiàn)自己的toString、hashCode、copy、equals方法
  1. case class person( 
  2.     name:String, 
  3.     age:Int 

對(duì)象與伴生對(duì)象

Scala單例對(duì)象是十分重要的,沒(méi)有像在Java一樣,有靜態(tài)類、靜態(tài)成員、靜態(tài)方法,但是Scala提供了object對(duì)象,這個(gè)object對(duì)象類似于Java的靜態(tài)類,它的成員、它的方法都默認(rèn)是靜態(tài)的。

定義單例對(duì)象并不代表定義了類,因此你不可以使用它來(lái)new對(duì)象。當(dāng)單例對(duì)象與某個(gè)類共享同一個(gè)名稱時(shí),它就被稱為這個(gè)類的伴生對(duì)象。

類和它的伴生對(duì)象必須定義在同一個(gè)源文件里。類被稱為這個(gè)單例對(duì)象的伴生類。

類和它的伴生對(duì)象可以互相訪問(wèn)其私有成員。

  1. object Test { 
  2.   private var name="大數(shù)據(jù)" 
  3.  
  4.   def main(args: Array[String]): Unit = { 
  5.     val test = new Test() 
  6.     println(test.update_name()) 
  7.   } 
  8.  
  9. class Test{ 
  10.   def update_name(): String ={ 
  11.     Test.name="左右手" 
  12.     Test.name 
  13.   } 
  14.  

特質(zhì)(trait)

scala trait相當(dāng)于java 的接口,實(shí)際上它比接口還功能強(qiáng)大。與接口不同的是,它還可以定義屬性和方法的實(shí)現(xiàn)。

一般情況下scala的類只能夠繼承單一父類,但是如果是trait 的話就可以繼承多個(gè),從結(jié)果來(lái)看就是實(shí)現(xiàn)了多重繼承(關(guān)鍵字with)。其實(shí)scala trait更像java的抽象類。

  1. object Test extends UserImp with AddressImp { 
  2.   override def getUserName(): String = ??? 
  3.  
  4.   override def getAddress(): String = ??? 
  5.  
  6. trait UserImp{ 
  7.   def getUserName():String  
  8.  
  9. trait AddressImp{ 
  10.   def getAddress():String 

模式匹配

以java 的 switch 為例,java 的 switch 僅僅會(huì)做一些基本類型的匹配,然后執(zhí)行一些動(dòng)作,并且是沒(méi)有返回值的。

而 scala 的 pattern matching match 則要強(qiáng)大得多,除了可以匹配數(shù)值,同時(shí)它還能匹配類型。

  1. def calculate(symbol:String): (String,String)=>String ={ 
  2.     symbol match { 
  3.       case "拼接方式1" => (a:String,b:String)=> s"拼接方式1:$a , $b" 
  4.       case "拼接方式2" => (a:String,b:String)=> s"拼接方式2: $b , $a" 
  5.     } 
  6.   } 

讓我吃驚的是(就短短幾行)

  1. 快排 
  2.  
  3. def quickSort(list: List[Int]): List[Int] = list match { 
  4.     case Nil => Nil 
  5.     case List() => List() 
  6.     case head :: tail => 
  7.       val (leftright) = tail.partition(_ < head) 
  8.       quickSort(left) ::: head :: quickSort(right
  9.   } 
  10.    
  11. 歸并 
  12.  
  13. def merge(left: List[Int], right: List[Int]): List[Int] = (leftright) match { 
  14.     case (Nil, _) => right 
  15.     case (_, Nil) => left 
  16.     case (x :: xTail, y :: yTail) => 
  17.       if (x <= y) x :: merge(xTail, right
  18.       else y :: merge(left, yTail) 

隱式轉(zhuǎn)換

Scala提供的隱式轉(zhuǎn)換和隱式參數(shù)功能,是非常有特色的功能。是Java等編程語(yǔ)言所沒(méi)有的功能。它可以允許你手動(dòng)指定,將某種類型的對(duì)象轉(zhuǎn)換成其他類型的對(duì)象。通過(guò)這些功能,可以實(shí)現(xiàn)非常強(qiáng)大,而且特殊的功能。

規(guī)則

(1)在使用隱式轉(zhuǎn)換之前,需要用import把隱式轉(zhuǎn)換引用到當(dāng)前的作用域里或者就在作用域里定義隱式轉(zhuǎn)換。

(2)隱式轉(zhuǎn)換只能在無(wú)其他可用轉(zhuǎn)換的前提下才能操作。如果在同一作用域里,對(duì)同一源類型定義一個(gè)以上的隱式轉(zhuǎn)換函數(shù),如果多種隱式轉(zhuǎn)換函數(shù)都可以匹配,那么編譯器將報(bào)錯(cuò),所以在使用時(shí)請(qǐng)移除不必要的隱式定義。

數(shù)據(jù)類型的隱式轉(zhuǎn)換

String類型是不能自動(dòng)轉(zhuǎn)換為Int類型的,所以當(dāng)給一個(gè)Int類型的變量或常量賦予String類型的值時(shí)編譯器將報(bào)錯(cuò)。但是.....

  1. implicit def strToInt(str: String) = str.toInt 
  2. def main(args: Array[String]): Unit = { 
  3.   val a:Int="100" 
  4.    
  5.   print(a) 

參數(shù)的隱式轉(zhuǎn)換

所謂的隱式參數(shù),指的是在函數(shù)或者方法中,定義一個(gè)用implicit修飾的參數(shù),此時(shí)Scala會(huì)嘗試找到一個(gè)指定類型的,用implicit修飾的對(duì)象,即隱式值,并注入?yún)?shù)。

  1. object Test { 
  2.   private var name="大數(shù)據(jù)" 
  3.   implicit val test = new Test 
  4.  
  5.   def getName(implicit test:Test): Unit ={ 
  6.     println(test.update_name()) 
  7.   } 
  8.   def main(args: Array[String]): Unit = { 
  9.     getName 
  10.   } 
  11.  
  12. class Test{ 
  13.   def update_name(): String ={ 
  14.     Test.name="左右手" 
  15.     Test.name 
  16.   } 
  17.  

 

責(zé)任編輯:武曉燕 來(lái)源: 大數(shù)據(jù)左右手
相關(guān)推薦

2021-01-27 10:28:21

CISO升職加薪首席信息安全官

2016-06-06 17:23:50

AndroidChrome OS

2009-06-24 14:10:22

2015-10-19 12:45:02

華三

2014-01-17 15:31:43

智能數(shù)據(jù)中心PDU

2018-12-10 07:22:27

物聯(lián)網(wǎng)預(yù)測(cè)分析安全威脅

2022-12-02 16:18:16

高并發(fā)架構(gòu)

2017-07-26 16:15:17

Python案例入門級(jí)

2020-06-08 17:51:28

戴爾

2021-12-24 10:01:55

勒索團(tuán)伙攻擊勒索軟件

2018-10-23 16:40:08

Python編程語(yǔ)言實(shí)用案例

2025-05-16 09:34:10

2021-07-21 18:20:25

創(chuàng)維

2020-11-10 14:09:48

高斯進(jìn)程神經(jīng)網(wǎng)絡(luò)高斯

2021-05-17 07:04:07

動(dòng)態(tài)代理面試

2022-11-28 08:44:46

死鎖面試線程

2019-10-15 06:47:46

人工智能PythonC

2021-01-13 15:02:40

戴爾

2018-04-26 16:15:02

數(shù)據(jù)庫(kù)MySQLMySQL 8.0

2018-03-19 14:43:28

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)