最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Scala函數(shù)式編程專題--scala集合和函數(shù)

 更新時(shí)間:2020年06月29日 11:06:34   作者:zzzzMing  
這篇文章主要介紹了scala集合和函數(shù)的的相關(guān)資料,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下

前情提要:

Scala函數(shù)式編程專題—— 函數(shù)式思想介紹

scala函數(shù)式編程專題——scala基礎(chǔ)語(yǔ)法介紹

前面已經(jīng)稍微介紹了scala的常用語(yǔ)法以及面向?qū)ο蟮囊恍┖?jiǎn)要知識(shí),這次是補(bǔ)充上一章的,主要會(huì)介紹集合和函數(shù)。

注意噢,函數(shù)和方法是不一樣的,方法是在類里面定義的,函數(shù)是可以單獨(dú)存在的(嚴(yán)格來說,在scala內(nèi)部,每個(gè)函數(shù)都是一個(gè)類)

一.scala集合介紹

還記得上一章介紹的object的apply方法嗎,很多數(shù)據(jù)結(jié)構(gòu)其實(shí)都用到了它,從而讓我們可以直接用List(...)這樣來新建一個(gè)List,而不用自己手動(dòng)new一個(gè)。

PS:注意,scala默認(rèn)的數(shù)據(jù)結(jié)構(gòu)都是不可變的,就是說一個(gè)List,沒法刪除或增加新的元素。當(dāng)然,也有“可變”的數(shù)據(jù)結(jié)構(gòu),后面會(huì)介紹到。

1.1 List

得益于apply方法,我們可以不通過new來新建數(shù)據(jù)結(jié)構(gòu)。

//通過工廠,新建一個(gè)List,這個(gè)List是不可變的
scala> val numbers = List(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
numbers: List[Int] = List(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)

1.2 元組Tuple

Tuple這個(gè)概念在python應(yīng)用比較廣泛,它可以將多種數(shù)據(jù)類型(Int,String,Double等)打包在一起

scala> val tup = (1,1,2.1,"tuple",'c') //將多種不同數(shù)據(jù)結(jié)構(gòu)打包一起,可以有重復(fù)
tup: (Int, Int, Double, String, Char) = (1,1,2.1,tuple,c)

但在scala中,Tuple是有長(zhǎng)度限制的,那就是一個(gè)Tuple最多只能有22個(gè)元素。

scala> val tup = (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)
tup: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) = (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)

//一個(gè)Tuple超過22個(gè)元素,報(bào)錯(cuò)了
scala> val tup = (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)
<console>:1: error: too many elements for tuple: 23, allowed: 22
val tup = (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)

可以看到上面,一但一個(gè)Tuple超過22個(gè)元素,就會(huì)報(bào)錯(cuò)了。至于為什么是22這個(gè)神奇的數(shù)字,好像一直沒有一個(gè)統(tǒng)一的論調(diào)。有人開玩笑的說23才對(duì),因?yàn)橛胁侩娪暗拿纸小禩he Number 23》~~

1.3 Map和Option

在說Map之前,需要先介紹Option,因?yàn)镸ap里面存的就是Option,這個(gè)后面介紹。

Option翻譯過來是選項(xiàng),本質(zhì)上,它也確實(shí)是一個(gè)選項(xiàng),用來告訴你存不存在。還是用實(shí)例說明吧:

//Option里面可以存普通數(shù)據(jù)類型
scala> val optionInt = Option(1)
optionInt: Option[Int] = Some(1)

scala> optionInt.get
res8: Int = 1
//但一個(gè)Option也可能為空
scala> val optionNone = Option(null)
optionNone: Option[Null] = None
//當(dāng)Option里面是空的時(shí)候,是get不出東西的,還會(huì)報(bào)錯(cuò)
scala> optionNone.get
java.util.NoSuchElementException: None.get
 at scala.None$.get(Option.scala:347)
 at scala.None$.get(Option.scala:345)
 ... 32 elided
//這個(gè)時(shí)候可以判斷它就是空的
scala> optionNone.isEmpty
res11: Boolean = true
//但可以用getOrElse()方法,當(dāng)Option里面有東西的時(shí)候,就返回那個(gè)東西,如果沒有東西,就返回getOrElse()的參數(shù)的內(nèi)容
scala> optionNone.getOrElse("this is null") //里面沒東西
res12: String = this is null
scala> optionInt.getOrElse("this is null") //里面有東西
res15: Any = 1

再說Map,Map里面的value的類型并不是你賦的那個(gè)數(shù)據(jù)類型,而是Option。即Map(key -> Option,key1 -> Option)。

scala> val map = Map("test1" -> 1,"test2" -> 2)
map: scala.collection.immutable.Map[String,Int] = Map(test1 -> 1, test2 -> 2)

scala> map.get("test1")
res16: Option[Int] = Some(1)

scala> map.get("test3")
res17: Option[Int] = None

scala> map.get("test3").getOrElse("this is null")
res18: Any = this is null

這樣的好處是什么呢?還記得在java里面,每次都得為java為空的情況做判斷的痛苦嗎。在scala,這些煩惱通通不存在。有了Option,媽媽再也不用擔(dān)心NullPointerException啦。

1.4 常用函數(shù)組合子

匿名函數(shù)

將集合的函數(shù)組合子,那肯定得先將匿名函數(shù)。如果有用過python中的lambda表達(dá)式,那應(yīng)該就很了解這種方式了。

前面說到,在scala中,函數(shù)就是對(duì)象,匿名函數(shù)也是函數(shù)。舉個(gè)簡(jiǎn)單的例子:

//創(chuàng)建一個(gè)匿名函數(shù)
scala> val addOne = (x: Int) => x + 1
addOne: (Int) => Int = <function1>

scala> addOne(1)
res4: Int = 2

注意,函數(shù)里面是可以不用return的,最后面的那個(gè)x+1就是匿名函數(shù)的返回值了。

map,reduce

因?yàn)閔adoop的出現(xiàn),MapReduce都被說爛了。雖然Hadoop的Mapreduce起源自函數(shù)式的map和reduce,但兩者其實(shí)是不一樣的。感興趣的可以看看我之前寫過的一篇:從分治算法到 Hadoop MapReduce

函數(shù)式里面的map呢,粗略的說,其實(shí)相當(dāng)一個(gè)有返回值的for循環(huán)。

scala> val list = List(1,2,3)
list: List[Int] = List(1, 2, 3)

scala> list.map(_ + 1) //這里的(_+1)其實(shí)就是一個(gè)匿名函數(shù) //讓List中每一個(gè)元素+1,并返回
res29: List[Int] = List(2, 3, 4)

至于reduce呢,也是像for循環(huán),只是不像map每次循環(huán)是當(dāng)前元素,reduce除了當(dāng)前元素,還有上一次循環(huán)的結(jié)果,還是看看例子吧:

scala> list.reduce((i,j) => i + j) //兩個(gè)兩個(gè)一起循環(huán),這里是讓兩個(gè)相加
res28: Int = 6

比如上面的例子,有1,2,3三個(gè)數(shù)。第一次循環(huán)的兩個(gè)是1,2,1+2就等于3,第二次循環(huán)就是上次的結(jié)果3和原本的3,3+3等于6,結(jié)果就是6。

filter

filter故名思意,就是過濾的意思,可以在filter中傳進(jìn)去一個(gè)匿名函數(shù),返回布爾值。返回true的則保留,返回false的丟棄。

scala> val numbers = List(1, 2, 3, 4)
numbers: List[Int] = List(1, 2, 3, 4)

//過濾出余2等于0的
scala> numbers.filter((i: Int) => i % 2 == 0)
res0: List[Int] = List(2, 4)

foldLeft

這個(gè)和reduce類似,也是遍歷,除了當(dāng)前元素,還有上一次迭代的結(jié)果。區(qū)別在于foldLeft有一個(gè)初始值。

scala> val numbers = List(1, 2, 3, 4)
numbers: List[Int] = List(1, 2, 3, 4)

//(m: Int, n: Int) => m + n這部分是一個(gè)匿名函數(shù)
scala> numbers.foldLeft(0)((m: Int, n: Int) => m + n)
res30: Int = 10

二.scala函數(shù)

在最前面有介紹到,函數(shù)就是對(duì)象。那為什么函數(shù)能直接運(yùn)行呢?這其實(shí)得益于object的apply這個(gè)語(yǔ)法糖。

偏函數(shù)

偏函數(shù)(PartialFunction),從某種意義上來說,偏函數(shù)也是scala中挺重要的一個(gè)語(yǔ)法糖。

偏函數(shù)它長(zhǎng)這樣:

PartialFunction[A, B] //接收一個(gè)A類型的參數(shù),返回B類型的參數(shù)

值得一提的是,scala中有一個(gè)關(guān)鍵字case,就是使用偏函數(shù)。繼續(xù)舉例子:

//下面的case就是一個(gè)偏函數(shù)PartialFunction[Int, String]
scala> val one: PartialFunction[Int, String] = { case 1 => "one" }
one: PartialFunction[Int,String] = <function1>

scala> one(1)
res11: String = Int

scala> one("one")
<console>:13: error: type mismatch;
 found : String("one")
 required: Int
 one("one")

case關(guān)鍵字會(huì)匹配符合條件的類型或值,如果不符合,會(huì)報(bào)錯(cuò)。內(nèi)部實(shí)現(xiàn)就不介紹了,知道是個(gè)常用語(yǔ)法糖就好。

而這個(gè)case關(guān)鍵字也正是實(shí)現(xiàn)scala模式匹配中,必不可少的一環(huán),有興趣的童鞋可以看看我這篇:scala模式匹配詳細(xì)解析

這里再說一個(gè)常見應(yīng)用吧,函數(shù)組合子中有一個(gè)collect,它需要的參數(shù)就是一個(gè)偏函數(shù)。下面看個(gè)有意思的例子:

//這個(gè)list里面的Any類型
scala> val list:List[Any] = List(1, 3, 5, "seven")
list: List[Any] = List(1, 3, 5, seven)

//使用map會(huì)報(bào)錯(cuò),因?yàn)閙ap接收的參數(shù)是普通函
scala> list.map { case i: Int => i + 1 }
scala.MatchError: seven (of class java.lang.String)
 at $anonfun$1.apply(<console>:13)
 at $anonfun$1.apply(<console>:13)
 at scala.collection.immutable.List.map(List.scala:277)
 ... 32 elided

 //但如果用collect函數(shù)就可以,因?yàn)閏ollect接收的參數(shù)是偏函數(shù),它會(huì)自動(dòng)使用偏函數(shù)的一些特性,所以可以自動(dòng)過濾掉不符合的數(shù)據(jù)類型
scala> list.collect { case i: Int => i + 1 }
res15: List[Int] = List(2, 4, 6)

因?yàn)閏ollect接收的參數(shù)是偏函數(shù),它會(huì)自動(dòng)使用偏函數(shù)的特性,自動(dòng)過濾不符合的數(shù)據(jù)類型,而map就做不到。

部分應(yīng)用函數(shù)

所謂部分應(yīng)用的意思,就是說,當(dāng)調(diào)用一個(gè)函數(shù)時(shí),可以僅傳遞一部分參數(shù)。而這樣會(huì)生成一個(gè)新的函數(shù),來個(gè)實(shí)例看看吧:

//定義一個(gè)打印兩個(gè)輸出參數(shù)的函數(shù)
scala> def partial(i:Int,j:Int) : Unit = {
 | println(i)
 | println(j)
 | }
partial: (i: Int,j: Int)Unit

//賦一個(gè)值給上面那個(gè)函數(shù),另一個(gè)參數(shù)不賦值,生成一個(gè)新的函數(shù)
scala> val partialFun = partial(5,_:Int)
partialFun: Int => Unit = <function1>

//只要一個(gè)參數(shù)就可以調(diào)用啦
scala> partialFun(10)
5
10

部分應(yīng)用函數(shù),主要是作用是代碼復(fù)用,同時(shí)也能夠增加一定的代碼可讀性。

當(dāng)然還有更多有意思的用法,后面有機(jī)會(huì)說到再說。

函數(shù)柯里化

剛開始,聽到柯里化的時(shí)候很奇怪??吕??啥玩意?

后來才知道,其實(shí)柯里是從curry音譯過來的,這個(gè)是個(gè)人名,就是發(fā)明了柯里化的發(fā)明人。

柯里化是把接受多個(gè)參數(shù)的函數(shù)變換成接受一個(gè)單一參數(shù)(最初函數(shù)的第一個(gè)參數(shù))的函數(shù),并且返回接受余下的參數(shù)且返回結(jié)果的新函數(shù)的技術(shù)。

看看具體是怎么使用吧:

//我們知道函數(shù)可以這樣定義,讓它接收兩個(gè)參數(shù)
scala> def curring(i:Int)(j: Int): Boolean = {false}
curring: (i: Int)(j: Int)Boolean

//可以把這個(gè)函數(shù)賦值給一個(gè)變量,注意變量的類型
scala> val curringVal:(Int => (Int => Boolean)) = curring _
curringVal: Int => (Int => Boolean) = <function1>

//可以讓這個(gè)變量接收一個(gè)參數(shù),又變成另一個(gè)函數(shù)了
scala> val curringVal_1 = curringVal(5)
curringVal_1: Int => Boolean = <function1>

//再用這個(gè)變量接收一個(gè)參數(shù),終于能返回結(jié)果了
scala> curringVal_1(10)
res32: Boolean = false

柯里化其實(shí)是把一個(gè)函數(shù)變成一個(gè)調(diào)用鏈的過程,和上面的部分應(yīng)用函數(shù)看起來有點(diǎn)像。

這幾個(gè)部分初次看可能不知道它究竟有什么用,其實(shí)這些功能的一個(gè)主要用途是函數(shù)式的依賴注入。通過這部分技術(shù)可以把被依賴的函數(shù)以參數(shù)的形式傳遞給上層函數(shù)。限于篇幅這里就先省略,后面再介紹。

結(jié)語(yǔ):

此次介紹的是scala集合的一些內(nèi)容,以及一些函數(shù)的特性,再說一遍,函數(shù)其實(shí)就是對(duì)象。

我一直有一種觀點(diǎn),在學(xué)習(xí)新的東西的時(shí)候,一些偏固定規(guī)則的東西,比如語(yǔ)法。不用全部記熟,只要知道大概原理,有個(gè)映像就行。

比如說scala的函數(shù)式編程,或是java的OOP,不需要抱有先把語(yǔ)法學(xué)完,再學(xué)習(xí)相關(guān)的編程理念,這在我看來是有點(diǎn)本末倒置了。

我一般的做法,是先熟悉大概的語(yǔ)法,然后去學(xué)習(xí)語(yǔ)言的精髓。當(dāng)碰到不懂的時(shí)候,再反過來查詢具體的語(yǔ)法,有了目標(biāo)之后,語(yǔ)法反而變得不是那么枯燥了。

以上只是我的一些個(gè)人看法,那么本篇到此就結(jié)束了。

到此這篇關(guān)于Scala函數(shù)式編程專題--scala集合和函數(shù)的文章就介紹到這了,更多相關(guān)scala函數(shù)式編程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺談如何降低軟件復(fù)雜性

    淺談如何降低軟件復(fù)雜性

    軟件的復(fù)雜性是我們程序員在日常開發(fā)中所必須面對(duì)的東西,學(xué)會(huì)如何 “弄清楚什么是軟件復(fù)雜性,找到導(dǎo)致軟件復(fù)雜的原因,并利用各種手法去戰(zhàn)勝軟件的復(fù)雜性” 是一門必備的能力。
    2021-05-05
  • 詳解提升場(chǎng)景文本識(shí)別中的語(yǔ)言模型

    詳解提升場(chǎng)景文本識(shí)別中的語(yǔ)言模型

    語(yǔ)言模型即根據(jù)當(dāng)前語(yǔ)境的上下文推斷當(dāng)前句子的意思。文本圖像中包含兩層信息:視覺紋理信息和語(yǔ)言信息。由于單純根據(jù)視覺紋理信息進(jìn)行文字識(shí)別缺少了對(duì)上下文的字符語(yǔ)義信息的挖掘,時(shí)常會(huì)導(dǎo)致錯(cuò)誤的文本識(shí)別結(jié)果(之后會(huì)詳細(xì)說明)。
    2021-05-05
  • 分享幾個(gè)快速提升工作效率的小工具(Listary等)

    分享幾個(gè)快速提升工作效率的小工具(Listary等)

    這篇文章主要介紹了分享幾個(gè)快速提升工作效率的小工具(Listary等),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • Idea 無法引用類問題解決辦法

    Idea 無法引用類問題解決辦法

    這篇文章主要介紹了 Idea 無法引用類問題解決辦法的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • 一文讀懂modbus slave和modbus poll使用說明

    一文讀懂modbus slave和modbus poll使用說明

    modbus poll和modbus slave是一款實(shí)用的modbus開發(fā)和調(diào)試工具,可以非常方便的進(jìn)行modbus調(diào)試,是非常有用的Modbus主機(jī)/從機(jī)模擬程序,這篇文章給大家介紹modbus slave和modbus poll使用說明,感興趣的朋友一起看看吧
    2021-04-04
  • 淺談軟件工程師的自我修養(yǎng)

    淺談軟件工程師的自我修養(yǎng)

    在本文中,我們將探討軟件開發(fā)過程中關(guān)于角色、重構(gòu)和質(zhì)量的問題。軟件不僅成為了一個(gè)必需品,更成為了一個(gè)競(jìng)爭(zhēng)優(yōu)勢(shì)。因?yàn)楸姸喙緡@軟件而競(jìng)爭(zhēng),軟件開發(fā)相關(guān)的事宜顯得越發(fā)重要。開發(fā)軟件的人—軟件工程師正顯得越發(fā)重要。
    2021-05-05
  • 深入分析java與C#底層控制能力區(qū)別及示例詳解

    深入分析java與C#底層控制能力區(qū)別及示例詳解

    這篇文章主要為大家深入分析java與C#底層控制能力不同的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2021-11-11
  • 淺談Scala模式匹配

    淺談Scala模式匹配

    這篇文章主要介紹了Scala模式匹配的的相關(guān)資料,文中講解非常詳細(xì),代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • vscode配置備份的操作代碼

    vscode配置備份的操作代碼

    這篇文章主要介紹了vscode配置備份的相關(guān)知識(shí),本文通過實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • 詳解基于深度學(xué)習(xí)的兩種信源信道聯(lián)合編碼

    詳解基于深度學(xué)習(xí)的兩種信源信道聯(lián)合編碼

    信源編碼是一個(gè)數(shù)據(jù)壓縮的過程,其目的是盡可能地將信源中的冗余度去掉;而信道編碼則是一個(gè)增加冗余的過程,通過適當(dāng)加入冗余度來達(dá)到抵抗信道噪聲,保護(hù)傳輸數(shù)據(jù)的目的。
    2021-05-05

最新評(píng)論

临沧市| 白城市| 全州县| 武城县| 德令哈市| 长岭县| 锡林浩特市| 左云县| 南昌市| 新竹市| 潮安县| 泸州市| 彭水| 通许县| 建水县| 石嘴山市| 凌云县| 神木县| 周口市| 济阳县| 辽中县| 子长县| 东明县| 淳安县| 岚皋县| 怀集县| 栾城县| 开封市| 乃东县| 宁津县| 重庆市| 孙吴县| 凤阳县| 仁化县| 奎屯市| 胶南市| 南澳县| 沾益县| 海口市| 江山市| 平度市|