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

Java函數(shù)式編程(八):字符串及方法引用

 更新時(shí)間:2014年09月26日 09:14:11   作者:有孚  
這篇文章主要介紹了Java函數(shù)式編程(八):字符串及方法引用,本文是系列文章的第8篇,其它文章請(qǐng)參閱本文底部的相關(guān)文章,需要的朋友可以參考下

第三章 字符串,比較器和過(guò)濾器

JDK引入的一些方法對(duì)寫(xiě)出函數(shù)式風(fēng)格的代碼很有幫助。JDK庫(kù)里的一些的類和接口我們已經(jīng)用得非常熟悉了,比如說(shuō)String,為了擺脫以前習(xí)慣的那種老的風(fēng)格,我們得主動(dòng)尋找機(jī)會(huì)來(lái)使用這些新的方法。同樣,當(dāng)我們需要用到只有一個(gè)方法的匿名內(nèi)部類時(shí),我們現(xiàn)在可以用lambda表達(dá)式來(lái)替換它了,不用再像原來(lái)那樣寫(xiě)的那么繁瑣了。

本章我們會(huì)使用lambda表達(dá)式和方法引用來(lái)遍歷字符串,實(shí)現(xiàn)Comparator接口,查看目錄中的文件,監(jiān)視文件及目錄的變更。上一章中介紹的一些方法還將繼續(xù)出現(xiàn)在這里,來(lái)幫助我們更好的完成這些任務(wù)。你學(xué)到的這些新技術(shù)有助于將冗長(zhǎng)繁瑣的代碼變得簡(jiǎn)潔,不僅能快速實(shí)現(xiàn)而且還易于維護(hù)。

遍歷字符串

chars()方法是String類里的一個(gè)新方法,它是CharSequence接口的一部分。想要快速遍歷String的字符序列的話,它是一個(gè)很有用的工具。有了這個(gè)內(nèi)部迭代器,我們可以方便的操作字符串中的各個(gè)字符。先用它來(lái)處理一個(gè)字符串試試。在這里順便介紹方法引用的幾種使用方式。

復(fù)制代碼 代碼如下:

final String str = "w00t";
str.chars()
     .forEach(ch -> System.out.println(ch));

chars()方法返回的是一個(gè)Stream對(duì)象,我們可以用它的內(nèi)部迭代器forEach()來(lái)進(jìn)行遍歷。在迭代器里,我們可以直接訪問(wèn)到字符串中的字符。下面是遍歷字符串并打印各個(gè)字符的輸出結(jié)果。
復(fù)制代碼 代碼如下:

119
48
48
116

這并不是我們想要的結(jié)果。我們希望看到的是字母,而輸出的卻是數(shù)字。這是因?yàn)閏hars()方法返回的是一個(gè)整型的Stream而不是字符型的。我們先了解下這個(gè)API,再去優(yōu)化輸出的結(jié)果。

前面的代碼中我們創(chuàng)建了一個(gè)lambda表達(dá)式,作為forEach方法的入?yún)?。它只是?jiǎn)單地把參數(shù)傳給了一個(gè)println()方法。由于這個(gè)操作很常見(jiàn),我們可以借助Java編譯器來(lái)對(duì)這段代碼進(jìn)行簡(jiǎn)化。就像在25頁(yè)的使用方法引用中那樣,用一個(gè)方法引用來(lái)代替它,讓編譯器來(lái)幫我們做參數(shù)路由。

我們已經(jīng)看到如何創(chuàng)建一個(gè)實(shí)例方法的方法引用了。比如,name.toUpperCase()方法,方法引用就是String::toUpperCase。而下面這個(gè)例子中,我們調(diào)用的是靜態(tài)引用System.out的一個(gè)實(shí)例方法。方法引用的兩個(gè)冒號(hào)左邊,可以是一個(gè)類名或者表達(dá)式。有了這個(gè)靈活性,我們可以很容易創(chuàng)建一個(gè)println()方法的引用,就像下面這樣。

復(fù)制代碼 代碼如下:

str.chars()
     .forEach(System.out::println);

可以看到,Java編譯器能很聰明的完成參數(shù)的路由?;叵胂耹ambda表達(dá)式和方法引用只能出現(xiàn)在接收函數(shù)式接口的地方,而Java編譯器會(huì)在那個(gè)地方生成一個(gè)對(duì)應(yīng)的方法(譯注:編譯器會(huì)生成函數(shù)式接口的實(shí)現(xiàn),這個(gè)實(shí)現(xiàn)只有一個(gè)方法)。之前我們用過(guò)的方法引用String::toUpperCase,傳給那個(gè)生成方法的參數(shù),最后會(huì)變成這個(gè)方法調(diào)用的目標(biāo)對(duì)象,就像這樣:parameter.toUpperCase()。這是因?yàn)檫@個(gè)方法引用是基于類名的(String)。而上面這個(gè)例子中的方法引用,是基于一個(gè)表達(dá)式的,它是PrintStream的一個(gè)實(shí)例,通過(guò)System.out來(lái)引用它。由于方法調(diào)用的對(duì)象已經(jīng)有了,Java編譯器決定用生成方法中的參數(shù)作為這個(gè)println方法的參數(shù):System.out.println(name)。

(譯注:其實(shí)主要是兩種場(chǎng)景,同樣是傳遞了一個(gè)方法引用,一個(gè)是把遍歷的對(duì)象,當(dāng)然方法調(diào)用的目標(biāo)對(duì)象,比如name.toUpperCase,另外一種是作為方法調(diào)用的參數(shù),比如System.out.println(name).)

用了方法引用之后代碼簡(jiǎn)潔多了,不過(guò)我們得去深入了解下它是如何運(yùn)行的。一旦我們熟悉了方法引用,就能自己想明白參數(shù)路由這些事了。

盡管這個(gè)例子中的代碼已經(jīng)夠簡(jiǎn)潔的了,但是輸出還是不如人意。我們想看到的是字母結(jié)果卻出現(xiàn)了數(shù)字。為了解決這個(gè)問(wèn)題,我們來(lái)寫(xiě)個(gè)方法將int輸出成字母。

復(fù)制代碼 代碼如下:

private static void printChar(int aChar) {
      System.out.println((char)(aChar));
}

使用方法引用可以很方便的完成輸出結(jié)果的優(yōu)化。
復(fù)制代碼 代碼如下:

str.chars()
     .forEach(IterateString::printChar);

現(xiàn)在雖然chars()返回的結(jié)果是int,但是也無(wú)所謂了,需要打印的時(shí)候,我們會(huì)將它轉(zhuǎn)化成字符。這回的輸出終于是字母了。
復(fù)制代碼 代碼如下:

w
0
0
t

如果我們希望從一開(kāi)始就處理的就是字符而不是int,可以在調(diào)用完chars后直接將int轉(zhuǎn)化成字符:
復(fù)制代碼 代碼如下:

str.chars()
     .mapToObj(ch -> Character.valueOf((char)ch))
     .forEach(System.out::println);

這里我們用到了chars()返回的Stream的一個(gè)內(nèi)部迭代器,當(dāng)然能用的可不止這一個(gè)方法。拿到Stream對(duì)象后,它的那些方法就任憑我們使用了,比如map(),filter(),reduce()等。我們可以使用filter()方法來(lái)過(guò)濾出那些是數(shù)字的字符:
復(fù)制代碼 代碼如下:

str.chars()
     .filter(ch -> Character.isDigit(ch))
     .forEach(ch -> printChar(ch));

這樣輸出的時(shí)候我們就只能看到數(shù)字了:
復(fù)制代碼 代碼如下:

0
0

同樣的,除了將lambda表達(dá)式傳給filter()和forEach()方法外,我們還可以使用方法引用。
復(fù)制代碼 代碼如下:

str.chars()
     .filter(Character::isDigit)
     .forEach(IterateString::printChar);

這里的方法引用把多余的參數(shù)路由給省掉了。在本例中,我們還看到了和前面兩個(gè)方法的引用不同的用法。第一次我們引用的是一個(gè)實(shí)例方法,第二次是一個(gè)靜態(tài)引用(System.out)上的方法。而這次則是一個(gè)靜態(tài)方法的引用——方法引用一直在默默的付出。

實(shí)例方法和靜態(tài)方法的引用看起來(lái)都一樣:比方說(shuō)String::toUpperCase和Character::isDigit。編譯器會(huì)判斷方法是實(shí)例方法還是靜態(tài)方法,來(lái)決定如何路由參數(shù)。如果是實(shí)例方法,它會(huì)將生成方法的入?yún)⒂米鞣椒ㄕ{(diào)用的目標(biāo)對(duì)象,比如 parameter,toUpperCase();(當(dāng)然也有例外,比如方法調(diào)用的目標(biāo)對(duì)象已經(jīng)指定了,像System::out.println())。另外如果是靜態(tài)方法的話,生成方法的入?yún)⒕蜁?huì)作為這個(gè)引用的方法的參數(shù),比如Character.isDigit(parameter)。152頁(yè)的附錄2,有詳細(xì)的方法引用的使用方法及語(yǔ)法說(shuō)明。

盡管方法引用用起來(lái)很方便,但還有一個(gè)問(wèn)題——方法命名沖突導(dǎo)致的二義性 。如果匹配的方法既有實(shí)例方法也有靜態(tài)方法,由于方法存在歧義編譯器會(huì)報(bào)錯(cuò)。比如這么寫(xiě),Double::toString,我們其實(shí)是想要把一個(gè)double類型轉(zhuǎn)化成字符串,但編譯器就不知道到底是該調(diào)用public String toString()的實(shí)例方法好,還是去調(diào)用public static String toString(double)方法,因?yàn)閮蓚€(gè)方法都是Double類的。如果你碰到這樣的情況,別灰心,就用lambda表達(dá)式來(lái)完成就好了。

一旦我們適應(yīng)了函數(shù)式編程,我們就可以在lambda表達(dá)式和方法引用之間隨心所欲地來(lái)回切換了。

本節(jié)中我們用了Java 8中的一個(gè)新方法來(lái)遍歷字符串。下面我們來(lái)看下Comparator接口又有了哪些改進(jìn)。

相關(guān)文章

  • Spring AOP與代理類的執(zhí)行順序級(jí)別淺析

    Spring AOP與代理類的執(zhí)行順序級(jí)別淺析

    這篇文章主要介紹了Spring AOP與代理類的執(zhí)行順序級(jí)別,關(guān)于 Spring AOP和Aspectj的關(guān)系,兩個(gè)都實(shí)現(xiàn)了切面編程,Spring AOP更多地是為了Spring框架本身服務(wù)的,而Aspectj具有更強(qiáng)大、更完善的切面功能
    2023-03-03
  • java FileOutputStream輸出流的使用解讀

    java FileOutputStream輸出流的使用解讀

    這篇文章主要介紹了java FileOutputStream輸出流的使用解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • Java觀察者模式例子

    Java觀察者模式例子

    這篇文章主要介紹了Java觀察者模式例子的相關(guān)資料,需要的朋友可以參考下
    2015-12-12
  • springboot發(fā)布dubbo服務(wù)注冊(cè)到nacos實(shí)現(xiàn)方式

    springboot發(fā)布dubbo服務(wù)注冊(cè)到nacos實(shí)現(xiàn)方式

    這篇文章主要介紹了springboot發(fā)布dubbo服務(wù)注冊(cè)到nacos實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 基于MockMvc進(jìn)行springboot調(diào)試(SpringbootTest)

    基于MockMvc進(jìn)行springboot調(diào)試(SpringbootTest)

    這篇文章主要介紹了基于MockMvc進(jìn)行springboot調(diào)試(SpringbootTest),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • SpringBoot 定時(shí)任務(wù)遇到的坑

    SpringBoot 定時(shí)任務(wù)遇到的坑

    這篇文章主要介紹了SpringBoot 定時(shí)任務(wù)遇到的坑,今天踩的這個(gè)坑和 cron 表達(dá)式有關(guān),文中給大家介紹了cron 表達(dá)式的解釋,需要的朋友一起看看吧
    2017-11-11
  • SpringBoot中的ImportSelector類動(dòng)態(tài)加載bean詳解

    SpringBoot中的ImportSelector類動(dòng)態(tài)加載bean詳解

    這篇文章主要介紹了SpringBoot中的ImportSelector類動(dòng)態(tài)加載bean詳解,ImportSelector接口是spring中導(dǎo)入外部配置的核心接口,根據(jù)給定的條件(通常是一個(gè)或多個(gè)注釋屬性)判定要導(dǎo)入那個(gè)配置類,在spring自動(dòng)化配置和@EnableXXX中都有它的存在,需要的朋友可以參考下
    2024-01-01
  • MyBatis通用的10種寫(xiě)法總結(jié)大全

    MyBatis通用的10種寫(xiě)法總結(jié)大全

    這篇文章主要給大家介紹了關(guān)于MyBatis通用的10種寫(xiě)法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • Java Integer.valueOf()和Integer.parseInt()的區(qū)別說(shuō)明

    Java Integer.valueOf()和Integer.parseInt()的區(qū)別說(shuō)明

    這篇文章主要介紹了Java Integer.valueOf()和Integer.parseInt()的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-08-08
  • javaweb在線支付功能實(shí)現(xiàn)代碼

    javaweb在線支付功能實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了javaweb在線支付功能的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-04-04

最新評(píng)論

大埔县| 邢台县| 鄂托克旗| 安达市| 左权县| 西丰县| 溧阳市| 新绛县| 合山市| 桓仁| 内黄县| 武定县| 墨玉县| 运城市| 武冈市| 屏南县| 宝清县| 盖州市| 永宁县| 合水县| 浦北县| 芜湖市| 孟连| 益阳市| 河南省| 横山县| 蓬安县| 丹东市| 宜黄县| 甘孜县| 永仁县| 陕西省| 遂川县| 贵溪市| 潍坊市| 平潭县| 长汀县| 宝山区| 洪泽县| 津南区| 马山县|