第三章 字符串,比較器和過濾器
JDK引入的一些方法對(duì)寫出函數(shù)式風(fēng)格的代碼很有幫助。JDK庫里的一些的類和接口我們已經(jīng)用得非常熟悉了,比如說String,為了擺脫以前習(xí)慣的那種老的風(fēng)格,我們得主動(dòng)尋找機(jī)會(huì)來使用這些新的方法。同樣,當(dāng)我們需要用到只有一個(gè)方法的匿名內(nèi)部類時(shí),我們現(xiàn)在可以用lambda表達(dá)式來替換它了,不用再像原來那樣寫的那么繁瑣了。
本章我們會(huì)使用lambda表達(dá)式和方法引用來遍歷字符串,實(shí)現(xiàn)Comparator接口,查看目錄中的文件,監(jiān)視文件及目錄的變更。上一章中介紹的一些方法還將繼續(xù)出現(xiàn)在這里,來幫助我們更好的完成這些任務(wù)。你學(xué)到的這些新技術(shù)有助于將冗長繁瑣的代碼變得簡潔,不僅能快速實(shí)現(xiàn)而且還易于維護(hù)。
遍歷字符串
chars()方法是String類里的一個(gè)新方法,它是CharSequence接口的一部分。想要快速遍歷String的字符序列的話,它是一個(gè)很有用的工具。有了這個(gè)內(nèi)部迭代器,我們可以方便的操作字符串中的各個(gè)字符。先用它來處理一個(gè)字符串試試。在這里順便介紹方法引用的幾種使用方式。
前面的代碼中我們創(chuàng)建了一個(gè)lambda表達(dá)式,作為forEach方法的入?yún)?。它只是簡單地把參?shù)傳給了一個(gè)println()方法。由于這個(gè)操作很常見,我們可以借助Java編譯器來對(duì)這段代碼進(jìn)行簡化。就像在25頁的使用方法引用中那樣,用一個(gè)方法引用來代替它,讓編譯器來幫我們做參數(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()方法的引用,就像下面這樣。
(譯注:其實(shí)主要是兩種場景,同樣是傳遞了一個(gè)方法引用,一個(gè)是把遍歷的對(duì)象,當(dāng)然方法調(diào)用的目標(biāo)對(duì)象,比如name.toUpperCase,另外一種是作為方法調(diào)用的參數(shù),比如System.out.println(name).)
用了方法引用之后代碼簡潔多了,不過我們得去深入了解下它是如何運(yùn)行的。一旦我們熟悉了方法引用,就能自己想明白參數(shù)路由這些事了。
盡管這個(gè)例子中的代碼已經(jīng)夠簡潔的了,但是輸出還是不如人意。我們想看到的是字母結(jié)果卻出現(xiàn)了數(shù)字。為了解決這個(gè)問題,我們來寫個(gè)方法將int輸出成字母。
實(shí)例方法和靜態(tài)方法的引用看起來都一樣:比方說String::toUpperCase和Character::isDigit。編譯器會(huì)判斷方法是實(shí)例方法還是靜態(tà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頁的附錄2,有詳細(xì)的方法引用的使用方法及語法說明。
盡管方法引用用起來很方便,但還有一個(gè)問題――方法命名沖突導(dǎo)致的二義性 。如果匹配的方法既有實(shí)例方法也有靜態(tài)方法,由于方法存在歧義編譯器會(huì)報(bào)錯(cuò)。比如這么寫,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á)式來完成就好了。
一旦我們適應(yīng)了函數(shù)式編程,我們就可以在lambda表達(dá)式和方法引用之間隨心所欲地來回切換了。
本節(jié)中我們用了Java 8中的一個(gè)新方法來遍歷字符串。下面我們來看下Comparator接口又有了哪些改進(jìn)。
新聞熱點(diǎn)
疑難解答
圖片精選