23篇大数据系列(二)scala基础知识全集(史上最全,建议收藏)
作者簡介:
藍橋簽約作者、大數(shù)據(jù)&Python領(lǐng)域優(yōu)質(zhì)創(chuàng)作者。管理多個大數(shù)據(jù)技術(shù)群,幫助大學(xué)生就業(yè)和初級程序員解決工作難題。
我的使命與愿景:持續(xù)穩(wěn)定輸出,賦能中國技術(shù)社區(qū)蓬勃發(fā)展!
大數(shù)據(jù)系列文章,從技術(shù)能力、業(yè)務(wù)基礎(chǔ)、分析思維三大板塊來呈現(xiàn),你將收獲:
??提升自信心,自如應(yīng)對面試,順利拿到實習(xí)崗位或offer;
??掌握大數(shù)據(jù)的基礎(chǔ)知識,與其他同事溝通無障礙;
??具備一定的項目實戰(zhàn)能力,對于大數(shù)據(jù)工作直接上手;
評論、點贊、收藏是對我最大的支持!!!
大數(shù)據(jù)工程師系列專欄:?面試真題、開發(fā)經(jīng)驗、調(diào)優(yōu)策略
大數(shù)據(jù)工程師知識體系:
大數(shù)據(jù)時代已經(jīng)到來
最近幾十年,高速發(fā)展的互聯(lián)網(wǎng),滲透進了我們生活的方方面面,整個人類社會都已經(jīng)被互聯(lián)網(wǎng)連接為一體。身處互聯(lián)網(wǎng)之中,我們無時無刻不在產(chǎn)生大量數(shù)據(jù),如瀏覽商品的記錄、成交訂單記錄、觀看視頻的數(shù)據(jù)、瀏覽過的網(wǎng)頁、搜索過的關(guān)鍵詞、點擊過的廣告、朋友圈的自拍和狀態(tài)等。這些數(shù)據(jù),既是我們行為留下的痕跡,同時也是描述我們自身最佳的證據(jù)。
2014年3月,馬云曾經(jīng)在北京的一次演講中說道:“人類正從IT時代走向DT時代”。7年過去了,正如馬云預(yù)想的那樣,大數(shù)據(jù)時代已經(jīng)到來了。
大數(shù)據(jù)工程師的工作內(nèi)容是什么?
而大數(shù)據(jù)時代,有一個關(guān)鍵性的崗位不得不提,那就是大數(shù)據(jù)工程師。想必大家也會好奇,大數(shù)據(jù)工程師,日常是做什么的呢??
| 1.數(shù)據(jù)采集 | 找出描述用戶或?qū)I(yè)務(wù)發(fā)展有幫助的數(shù)據(jù),并將定義相關(guān)的數(shù)據(jù)格式,交由業(yè)務(wù)開發(fā)部門負責(zé)收集對應(yīng)的數(shù)據(jù)。 |
| 2.ETL工程? | 對收集到的數(shù)據(jù),進行各種清洗、處理、轉(zhuǎn)化等操作,完成格式轉(zhuǎn)換,便于后續(xù)分析,保證數(shù)據(jù)質(zhì)量,以便得出可以信賴的結(jié)果。 |
| 3.構(gòu)建數(shù)倉 | 將數(shù)據(jù)有效治理起來,構(gòu)建統(tǒng)一的數(shù)據(jù)倉庫,讓數(shù)據(jù)與數(shù)據(jù)間建立連接,碰撞出更大的價值。 |
| 4.數(shù)據(jù)建模 | 基于已有的數(shù)據(jù),梳理數(shù)據(jù)間的復(fù)雜關(guān)系,建立恰當(dāng)?shù)臄?shù)據(jù)模型,便于分析出有價值的結(jié)論。 |
| 5.統(tǒng)計分析 | 對數(shù)據(jù)進行各種維度的統(tǒng)計分析,建立指標(biāo)體系,系統(tǒng)性地描述業(yè)務(wù)發(fā)展的當(dāng)前狀態(tài),尋找業(yè)務(wù)中的問題,發(fā)現(xiàn)新的優(yōu)化點與增長點。 |
| 6.用戶畫像 | 基于用戶的各方面數(shù)據(jù),建立對用戶的全方位理解,構(gòu)建每個特定用戶的畫像,以便針對每個個體完成精細化運營。 |
大數(shù)據(jù)工程師必備技能
那么,問題來了,如果想成為一名大數(shù)據(jù)工程師,勝任上述工作內(nèi)容,需要具備什么樣的條件?擁有什么樣的知識呢?
| 分類 | 子分類 | 技能 | 描述 |
| 技 術(shù) 能 力 | 編程基礎(chǔ) | Java基礎(chǔ) | 大數(shù)據(jù)生態(tài)必備的java基礎(chǔ) |
| Scala基礎(chǔ) | Spark相關(guān)生態(tài)的必備技能 | ||
| SQL基礎(chǔ) | 數(shù)據(jù)分析師的通用語言 | ||
| SQL進階 | 完成復(fù)雜分析的必備技能 | ||
| 大數(shù)據(jù)框架 | HDFS&YARN | 大數(shù)據(jù)生態(tài)的底層基石 | |
| Hive基礎(chǔ) | 大數(shù)據(jù)分析的常用工具 | ||
| Hive進階 | 大數(shù)據(jù)分析師的高級裝備 | ||
| Spark基礎(chǔ) | 排查問題必備的底層運行原理 | ||
| Spark SQL | 應(yīng)對復(fù)雜任務(wù)的利刃 | ||
| 工具 | Hue&Zeppelin | 通用的探索分析工具 | |
| Azkaban | 作業(yè)管理調(diào)度平臺 | ||
| Tableau | 數(shù)據(jù)可視化平臺 | ||
| 業(yè)務(wù)基礎(chǔ) | 數(shù)據(jù)收集 | 數(shù)據(jù)是如何收集到的? | |
| ETL工程 | 怎么清洗、處理和轉(zhuǎn)化數(shù)據(jù)? | ||
| 數(shù)據(jù)倉庫基礎(chǔ) | 如何完成面向分析的數(shù)據(jù)建模? | ||
| 元數(shù)據(jù)中心 | 如何做好數(shù)據(jù)治理? | ||
| 分析思維 | 數(shù)據(jù)分析思維方法論 | 怎么去分析一個具體問題? | |
| 排查問題思維 | 如何高效排查數(shù)據(jù)問題? | ||
| 指標(biāo)體系 | 怎么讓數(shù)據(jù)成體系化? | ||
Scala為什么會如此重要,作者覺得主要有以下三點原因:
1、因為spark?
大部分從事大數(shù)據(jù)的工程師是先了解Spark進而再去選擇學(xué)習(xí)Scala的,因為Spark是用Scala開發(fā)的。現(xiàn)在Spark是大數(shù)據(jù)領(lǐng)域的殺手級應(yīng)用框架,只要搭建了大數(shù)據(jù)平臺,都會大量使用Spark來處理和分析數(shù)據(jù),而要想學(xué)好Spark,Scala這一關(guān)必須是要過的。順便說一句,Kafka也是基于Scala開發(fā)的。
2、無縫對接大數(shù)據(jù)生態(tài)組件?
眾所周知,大數(shù)據(jù)生態(tài)的大部分組件都是java語言開發(fā)的。而Scala是一門基于JVM的語言,可以與java無縫混編,因此可以很好地融合到大數(shù)據(jù)生態(tài)圈。
3、適合大數(shù)據(jù)處理與機器學(xué)習(xí)?
Scala的語法簡潔而富有表達力,更容易掌握。Scala將面向?qū)ο笈c函數(shù)式編程相結(jié)合,功能強大且簡練,非常適合用于處理各種數(shù)據(jù)。因此,在大數(shù)據(jù)處理與機器學(xué)習(xí)中占有重要的地位。
針對大數(shù)據(jù)分析師必須掌握的scala基礎(chǔ)知識,本文的講解思路如下:
第1部分:scala特性。主要講解面向?qū)ο筇匦浴⒑瘮?shù)式編程、靜態(tài)類型、擴展性和并發(fā)性。
第2部分:表達式。在scala中一切皆為表達式,理解表達式是理解其語法的前提。
第3部分:方法與函數(shù)。主要講兩者之間的區(qū)別和轉(zhuǎn)換。
第4部分:模式匹配。講解常用的幾種模式,并舉例說明。
第5部分:scala?trait。講解特質(zhì)的基本特性和示例。
第6部分:集合操作。主要針對常用集合和集合函數(shù)的講解和介紹。
第7部分:讀取數(shù)據(jù)源。只針對scala如何通過Source類讀取數(shù)據(jù)源進行簡單介紹。
第8部分:隱式轉(zhuǎn)換、隱式參數(shù)。主要講解Java和scala之間的類型轉(zhuǎn)換,以及通過一個實例介紹一下隱式參數(shù)的概念。
第9部分:正則匹配。主要講解如何寫正則相關(guān)的代碼。
第10部分:異常處理。介紹scala和java的異常有何區(qū)別。
第11部分:類型層級。主要介紹scala的類型層級體系。
第12部分:基本數(shù)值類型轉(zhuǎn)換。講解scala與java基本數(shù)值類型轉(zhuǎn)換常遇到的問題。
scala基礎(chǔ)知識
一、Scala特性
面向?qū)ο筇匦?
Scala是一種純面向?qū)ο蟮恼Z言,徹底貫徹萬物皆對象理念。對象的類型和行為是由類和特質(zhì)來描述的。Scala引入特質(zhì)(trait)來改進Java的對象模型,使得可以通過混入特質(zhì)的方式,擴展類的功能。
函數(shù)式編程?
Scala也是一種函數(shù)式語言,函數(shù)也能當(dāng)成值來傳遞。Scala提供了輕量級的語法用以定義匿名函數(shù),支持高階函數(shù),允許嵌套多層函數(shù),并支持柯里化。Scala的case class及其內(nèi)置的模式匹配相當(dāng)于函數(shù)式編程語言中常用的代數(shù)類型。
靜態(tài)類型?
Scala擁有一個強大表達能力的類型系統(tǒng),通過編譯時檢查,保證代碼的安全性和一致性。Scala具備類型推斷的特性,這使得開發(fā)者可以不去額外標(biāo)明重復(fù)的類型信息,讓代碼看起來更加整潔易讀。
?擴展性?
Scala的設(shè)計秉承一項事實,即在實踐中,某個領(lǐng)域特定的應(yīng)用程序開發(fā)往往需要特定于該領(lǐng)域的語言擴展。Scala提供了許多獨特的語言機制,可以以庫的形式輕易無縫添加新的語言結(jié)構(gòu)。
二、表達式
在scala中,一切皆為表達式。scala非常推崇表達式語法,因為表達式語法,對函數(shù)式編程是非常友好的。對開發(fā)者而言,表達式語法,使得代碼非常簡潔易讀。
舉個例子,我們在定義方法時,會和聲明變量一樣,使用等號(=)連接,等號左側(cè)是函數(shù)名、參數(shù)列表和返回值類型(可以省略),而等號右邊便是一個由大括號({})包裹的多行表達式。
表達式,是一定會有返回值的。在java中使用void來聲明無返回值的方法,而在scala里,這種情況也會有返回值,會返回一個Unit,這是一個特定的值,表示忽略方法的返回值。
三、方法與函數(shù)
初學(xué)scala時,往往會覺得方法和函數(shù)的概念有些模糊,在使用中可能會搞不清楚到底該使用方法還是函數(shù)。那怎么區(qū)分呢?關(guān)鍵是看這個函數(shù)是否在類中定義,在類中定義就是方法,所以Scala 方法是類的一部分。Scala 中的函數(shù)則是一個完整的對象,可以賦給一個變量。不過,在scala中,方法和函數(shù)是可以相互轉(zhuǎn)化的。下面我們重點說下,如何把方法轉(zhuǎn)為函數(shù)。
方法轉(zhuǎn)函數(shù)
上文中提到任何方法都是在聲明一個表達式,所以將方法轉(zhuǎn)為函數(shù)也就非常簡單了,相當(dāng)于是把方法指向的表達式,又重新賦給了一個函數(shù)變量,這就是顯式轉(zhuǎn)化。還有另外一種寫法,是通過偏應(yīng)用函數(shù)的方式,將方法轉(zhuǎn)化為一個新的函數(shù),稱作隱式轉(zhuǎn)化。
1)隱式轉(zhuǎn)化
val f2 = f1 _2)顯式轉(zhuǎn)化
val f2: (Int) => Int = f1四、模式匹配
模式匹配是檢查某個值是否匹配某一個模式的機制。它是Java中的switch語句的升級版,同樣可以用于替代一系列的 if/else 語句,以下介紹幾種常用的模式匹配:常量模式、變量模式、通配符模式。
常量模式
常量模式匹配,就是在模式匹配中匹配常量。
object ConstantPattern{ def main(args:Array[String]) :Unit = { //模式匹配結(jié)果作為函數(shù)返回值 def patternShow(x : Any) = x match { //常量模式 case 5 => "五" case true => "真" case "test" => "字符串" case null => "null值" case Nil => "空列表" //變量模式 case x => "變量" //通配符模式 case _ => "通配符" } }} 變量模式和通配符模式,都可以匹配任意值,他們之間的區(qū)別是,變量模式匹配成功后,該變量中會存儲匹配成功的值,在后續(xù)的代碼中還可以引用,而通配符模式匹配成功后,不能再引用匹配到的值。另外要注意的是,由于模式匹配是按順序匹配的,因此變量模式和通配符模式要寫在表達式的最后面。類型匹配模式
可以匹配輸入變量的類型。
object TypePattern{ def main(args:Array[String]) :Unit = { //類型匹配模式 def typePattern(t : Any) = t match { case t : String => "String" case t : Int => "Intger" case t : Double => "Double" case _ => "Other Type" } }}case class模式
構(gòu)造器模式指的是,直接在case語句后面接類構(gòu)造器,匹配的內(nèi)容放置在構(gòu)造器參數(shù)中。
object CaseClassPattern{ def main(args:Array[String]) :Unit = { //定義一個Person實例 val p = new Person("nyz",27) //case class 模式 def constructorPattern(p : Person) = p match { case Person(name,age) => "name =" + name + ",age =" + age case _ => "Other" } }}模式守衛(wèi)
為了讓匹配更加具體,可以使用模式守衛(wèi),也就是在模式后面加上if判斷語句。
object ConstantPattern{ def main(args:Array[String]) :Unit = { //模式匹配結(jié)果作為函數(shù)返回值 def patternShow(x : Any) = x match { //模式守衛(wèi) case x if(x == 5) => "守衛(wèi)" //通配符模式 case _ => "通配符" } }}Option匹配
在Scala中Option類型樣例類用來表示可能存在或也可能不存在的值(Option的子類有Some和None)。Some包裝了某個值,None表示沒有值。
class OptionDemo { val map = Map (("a",18),("b",81))??//get方法返回的類型就是Option[Int] map.get("b") match { case some(x) => println(x) case None => println("不存在") }}五、Scala Trait(特質(zhì))
Scala Trait(特質(zhì)) 相當(dāng)于 Java 的接口,但實際上它比接口的功能強大。與接口不同的是,它還可以定義屬性和方法的實現(xiàn)。
一般情況下Scala的類只能夠繼承單一父類,但可以使用with關(guān)鍵字混入多個 Trait(特質(zhì)) 。不過,如果一個scala類沒有父類,那么它混入的第一個特質(zhì)需要使用extends關(guān)鍵字,之后混入的特質(zhì)使用with關(guān)鍵字。
Trait(特質(zhì)) 定義的方式與類相似,但它使用的關(guān)鍵字是 trait,如下所示:
trait Equal { def isEqual(x: Any): Boolean def isNotEqual(x: Any): Boolean = !isEqual(x)}以上特質(zhì)(Equal)由兩個方法組成:isEqual 和 isNotEqual。isEqual 方法沒有定義方法的實現(xiàn),isNotEqual定義了方法的實現(xiàn)。子類繼承特質(zhì)可以實現(xiàn)未被實現(xiàn)的方法。
以下演示了特質(zhì)的完整實例:
trait Equal { def isEqual(x: Any): Boolean def isNotEqual(x: Any): Boolean = !isEqual(x)} class Point(xc: Int, yc: Int) extends Equal { val x: Int = xc val y: Int = yc def isEqual(obj: Any) = obj.isInstanceOf[Point] && obj.asInstanceOf[Point].x == x} object Test { def main(args: Array[String]) { val p1 = new Point(2, 3) val p2 = new Point(2, 4) val p3 = new Point(3, 3) println(p1.isNotEqual(p2)) println(p1.isNotEqual(p3)) println(p1.isNotEqual(2)) }}執(zhí)行以上代碼,輸出結(jié)果為:
$ scalac Test.scala $ scala -cp . Testfalsetruetrue六、集合操作
常用集合
通過下面的代碼,可以了解常用集合的創(chuàng)建方式
// 定義整型 List,其元素以線性方式存儲,可以存放重復(fù)對象。val x = List(1,2,3,4) // 定義 Set,其對象不按特定的方式排序,并且沒有重復(fù)對象。val x = Set(1,3,5,7) // 定義 Map,把鍵對象和值對象映射的集合,它的每一個元素都包含一對鍵對象和值對象。val x = Map("one" -> 1, "two" -> 2, "three" -> 3) // 創(chuàng)建兩個不同類型元素的元組,元組是不同類型的值的集合val x = (10, "Bigdata") // 定義 Option,表示有可能包含值的容器,也可能不包含值。val x:Option[Int] = Some(5)集合函數(shù)
工作中操作 Scala 集合時,一般會進行兩類操作:轉(zhuǎn)換操作(transformation )和行動操作(action)。第一種操作類型將集合轉(zhuǎn)換為另一個集合,第二種操作類型返回某些類型的值。
1)最大值和最小值
先從行動函數(shù)開始。在序列中查找最大或最小值是一個極常見的需求。
先看一下簡單的例子。
val numbers = Seq(11, 2, 5, 1, 6, 3, 9) numbers.max //11 numbers.min //1對于這種簡單數(shù)據(jù)集合,Scala的函數(shù)式特性顯露無疑,如此簡單的取到了最大值和最小值。再來看一個數(shù)據(jù)集合復(fù)雜的例子。
case class Book(title: String, pages: Int) val books = Seq( Book("Future of Scala developers", 85), Book("Parallel algorithms", 240), Book("Object Oriented Programming", 130), Book("Mobile Development", 495)) //下面代碼返回Book(Mobile Development,495)books.maxBy(book => book.pages) //下面代碼返回Book(Future of Scala developers,85)books.minBy(book?=>?book.pages)minBy & maxBy方法解決了復(fù)雜數(shù)據(jù)的問題。
2)篩選-Filter
對集合進行過濾,返回滿足條件的元素的新集合,比如過濾一組數(shù)據(jù)中的偶數(shù)。
val numbers = Seq(1,2,3,4,5,6,7,8,9,10) numbers.filter(n => n % 2 == 0)//上面返回Seq(2,4,6,8,10)獲取頁數(shù)大于300頁的書。
val books = Seq( Book("Future of Scala developers", 85), Book("Parallel algorithms", 240), Book("Object Oriented Programming", 130), Book("Mobile Development", 495)) books.filter(book => book.pages >= 300)//上面返回Seq(Book("Mobile?Development",?495))還有一個與 filter類似的方法是 filterNot,也就是篩選出不滿足條件的對象。
3)Flatten
它的作用是將多個集合展開,組成一個新的集合,舉例說明。
val abcd = Seq('a', 'b', 'c', 'd')val efgj = Seq('e', 'f', 'g', 'h')val ijkl = Seq('i', 'j', 'k', 'l')val mnop = Seq('m', 'n', 'o', 'p')val qrst = Seq('q', 'r', 's', 't')val uvwx = Seq('u', 'v', 'w', 'x')val yz = Seq('y', 'z') val alphabet = Seq(abcd, efgj, ijkl, mnop, qrst, uvwx, yz) alphabet.flatten執(zhí)行后返回下面的集合:
List('a',?'b',?'c',?'d',?'e',?'f',?'g',?'h',?'i',?'j',?'k',?'l',?'m',?'n',?'o',?'p',?'q',?'r',?'s',?'t',?'u',?'v',?'w',?'x',?'y',?'z')4)集合運算函數(shù)
集合運算即差集、交集和并集操作。
val num1 = Seq(1, 2, 3, 4, 5, 6)val num2 = Seq(4, 5, 6, 7, 8, 9) //返回List(1, 2, 3)num1.diff(num2) //返回List(4, 5, 6)num1.intersect(num2) //返回List(1, 2, 3, 4, 5, 6, 4, 5, 6, 7, 8, 9)num1.union(num2) //合并后再去重,返回List(1, 2, 3, 4, 5, 6, 7, 8, 9)num1.union(num2).distinct5)map函數(shù)
map 函數(shù)的邏輯是遍歷集合并對每個元素調(diào)用傳入的函數(shù)進行處理。
val numbers = Seq(1,2,3,4,5,6) //返回List(2, 4, 6, 8, 10, 12)numbers.map(n => n * 2) val chars = Seq('a', 'b', 'c', 'd') //返回List(A, B, C, D)chars.map(ch?=>?ch.toUpper)6)flatMap
它將map & flatten組合起來,請看下面的操作。
val abcd = Seq('a', 'b', 'c', 'd') //List(A, a, B, b, C, c, D, d)abcd.flatMap(ch?=>?List(ch.toUpper,?ch))從結(jié)果可以看出來是先做的map,然后做的flatten
7)forall?& exists
forall是對整個集合做判斷,當(dāng)集合中的所有元素都滿足條件時,返回true。而exists則是只要有一個元素滿足條件就返回true。
val numbers = Seq(3, 7, 2, 9, 6, 5, 1, 4, 2) //返回turenumbers.forall(n => n < 10) //返回falsenumbers.forall(n => n > 5) //返回truenumbers.exists(n?=>?n?>?5)七、讀取數(shù)據(jù)源
讀取外部數(shù)據(jù)源是開發(fā)中很常見的需求,如在程序中讀取外部配置文件并解析,獲取相應(yīng)的執(zhí)行參數(shù)。這里只針對scala如何通過Source類讀取數(shù)據(jù)源進行簡單介紹。
import scala.io.Sourceobject ReadFile { //讀取ClasPath下的配置文件 val file = Source.fromInputStream(this.getClass.getClassLoader.getResourceAsStream("app.conf")) //一行一行讀取文件,getLines()表示讀取文件所有行 def readLine: Unit ={ for(line <- file.getLines()){ println(line) } } //讀取網(wǎng)絡(luò)上的內(nèi)容 def readNetwork: Unit ={ val file = Source.fromURL("http://www.baidu.com") for(line <- file.getLines()){ println(line) } } //讀取給定的字符串-多用于調(diào)試 val source = Source.fromString("test") }八、隱式轉(zhuǎn)換
隱式轉(zhuǎn)換是Scala中一種非常有特色的功能,是其他編程語言所不具有的,可以實現(xiàn)將某種類型的對象轉(zhuǎn)換為另一種類型的對象。數(shù)據(jù)分析工作中,最常使用到的就是java和scala集合之間的互相轉(zhuǎn)換,轉(zhuǎn)換以后就可以調(diào)用另一種類型的方法。scala提供了scala.collection.JavaConversions類,只要引入此類中相應(yīng)的隱式轉(zhuǎn)化方法,在程序中就可以用相應(yīng)的類型來代替要求的類型。
如通過以下轉(zhuǎn)換,scala.collection.mutable.Buffer自動轉(zhuǎn)換成了java.util.List。
import scala.collection.JavaConversions.bufferAsJavaListscala.collection.mutable.Buffer?=>?java.util.List同樣,java.util.List也可以轉(zhuǎn)換成scala.collection.mutable.Buffer。
import scala.collection.JavaConversions.asScalaBufferjava.util.List?=>?scala.collection.mutable.Buffer所有可能的轉(zhuǎn)換匯總?cè)缦?#xff0c;雙向箭頭表示可互相轉(zhuǎn)換,單箭頭則表示只有左邊可轉(zhuǎn)換到右邊。
import scala.collection.JavaConversions._ scala.collection.Iterable <=> java.lang.Iterablescala.collection.Iterable <=> java.util.Collectionscala.collection.Iterator <=> java.util.{ Iterator, Enumeration }scala.collection.mutable.Buffer <=> java.util.Listscala.collection.mutable.Set <=> java.util.Setscala.collection.mutable.Map <=> java.util.{ Map, Dictionary }scala.collection.concurrent.Map <=> java.util.concurrent.ConcurrentMap scala.collection.Seq => java.util.Listscala.collection.mutable.Seq => java.util.Listscala.collection.Set => java.util.Setscala.collection.Map => java.util.Mapjava.util.Properties???=>?scala.collection.mutable.Map[String,?String]隱式參數(shù)
所謂隱式參數(shù),指的是在函數(shù)或者方法中,定義使用implicit修飾的參數(shù)。當(dāng)調(diào)用該函數(shù)或方法時,scala會嘗試在變量作用域中找到一個與指定類型相匹配的使用implicit修飾的對象,即隱式值,注入到函數(shù)參數(shù)中函數(shù)體使用。示例如下:
class SayHello{ def write(content:String) = println(content)}implicit val sayHello=new SayHello def saySomething(name:String)(implicit sayHello:SayHello){ sayHello.write("Hello," + name)} saySomething("Scala") //打印 Hello,Scala值得注意的是,隱式參數(shù)是根據(jù)類型匹配的,因此作用域中不能同時出現(xiàn)兩個相同類型的隱式變量,否則編譯時會拋出隱式變量模糊的異常。
九、正則匹配
正則的概念、作用和規(guī)則都在上一篇《大數(shù)據(jù)分析工程師入門--1.Java基礎(chǔ)》中已經(jīng)完整的講述了,這里將通過示例來講解下在scala中正則相關(guān)代碼怎么寫:
定義
val?TEST_REGEX?=?"home\\*(classification|foundation|my_tv)\\*[0-9-]{0,2}([a-z_]*)".r使用
//path是用來匹配的字符串TEST_REGEX findFirstMatchIn path match { case Some(p) => { //獲取TEST_REGEX中的第一個括號里正則片段匹配到的內(nèi)容 launcher_area_code = p.group(1) //獲取TEST_REGEX中的第二個括號里正則片段匹配到的內(nèi)容 launcher_location_code = p.group(2) }}十、異常處理
學(xué)習(xí)過Java的同學(xué)對異常一定并不陌生,異常通常是程序執(zhí)行過程中遇到問題時,用來打斷程序執(zhí)行的重要方式。關(guān)于異常處理的注意事項,在上一講《大數(shù)據(jù)分析工程師入門--1.Java基礎(chǔ)》里已經(jīng)講過了,這里就不再贅述了。我們重點來講下scala和java在異常這個特性的設(shè)計上的不同。
1. 捕獲異常的方式略有不同
java中是通過多個catch子句來捕獲不同類型的異常,而在scala中是通過一個catch子句,加上模式匹配的類型匹配方式來捕獲不同類型的異常。如下圖所示:
2.scala沒有checked異常
在java中,非運行時異常在編譯期是會被強制檢查的,要么寫try...catch...處理,要么使用throws關(guān)鍵字,將異常拋給調(diào)用者處理。而在scala中,更推崇通過使用函數(shù)式結(jié)構(gòu)和強類型來減少對異常及其處理的依賴。因此scala不支持檢查型異常(checked exception)。
當(dāng)使用scala調(diào)用java類庫時,scala會把java代碼中聲明的異常,轉(zhuǎn)換為非檢查型異常。
3.scala在throw異常時是有返回值的
在scala的設(shè)計中,所有表達式都是有返回值的。那么,自然throw表達式也不例外,throw表達式的返回值為Nothing。由于Nothing類型是所有類型的子類型,因此throw表達式可以出現(xiàn)在任意位置,而不會影響到類型的推斷。
十一、類型層級
在scala中,所有的值都是有類型的,包括數(shù)值型值和函數(shù),比java更加徹底地貫徹了萬物皆對象的理念。因此,scala有一套自己的類型層級,如下圖所示:
(圖片來自于網(wǎng)絡(luò))
如圖中所示,scala的頂級類是Any,下面包含兩個子類,AnyVal和AnyRef,其中AnyVal是所有值類型的父類,其中包含一個特殊的值Unit;而AnyRef是所有引用類型的父類,所有java類型和非值類型的scala類型都是它的子類。其中,有兩個比較特殊的底層子類型,一個是Null,它是所有引用類型的子類型,可以賦給任何引用類型變量;另一個是Nothing,它是所有類型的子類,因此既可以賦給引用類型變量,也可以賦給值類型變量。
十二、基本數(shù)值類型轉(zhuǎn)換
在scala中,通常會自動進行java和scala之間基本數(shù)值類型的轉(zhuǎn)換,并不需要單獨去處理。所以,在我們的感受中,通常java和scala的基本數(shù)據(jù)類型是可以無縫銜接的。但是,有一種情況是例外的,那就是當(dāng)你引用第三方的java類庫,而在它的代碼中接收參數(shù)是Object類型,之后又對傳入對象的實際數(shù)值類型做判斷時,通常會失敗報錯。
原因很簡單,第三方j(luò)ava類庫,使用java語言編寫,它只認(rèn)得java的類型。當(dāng)接收參數(shù)為Object類型時,scala默認(rèn)不會轉(zhuǎn)換成java的數(shù)值類型,這樣當(dāng)判斷對象的具體數(shù)值類型時,會出現(xiàn)不認(rèn)識scala對象類型的異常。
解決方案也很簡單,只需要在傳入第三方類庫方法前,手動包裝成java類型即可。以下是代碼示例,本例演示了DBUtils類庫傳入scala類型時的處理,只展示了部分代碼:
//由于java和scala中的類型短名稱重名,為避免歧義,進行了重命名import java.lang.{Long => JLong, Double => JDouble}//conn為數(shù)據(jù)庫連接,sql為要執(zhí)行的SQL語句queryRunner.update(conn,?sql,?new?JLong(1L),?new?JDouble(2.2))總結(jié)
本文結(jié)合實際工作經(jīng)驗,把scala中最常用到的一些知識點進行了梳理,要想成為一名初級大數(shù)據(jù)工程師,這些知識是必須要掌握的。
大數(shù)據(jù)俱樂部、數(shù)據(jù)與智能:??https://blog.csdn.net/weixin_39032019/article/details/117997723
整理不易,評論、點贊、收藏是對我最大的支持!!!
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的23篇大数据系列(二)scala基础知识全集(史上最全,建议收藏)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: opencv图像处理中的一些滤波器+利用
- 下一篇: 实验四51单片机并口实验