亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

第三章 字符串,比較器和過濾器

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

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

遍歷字符串

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

復制代碼 代碼如下:

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

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

119
48
48
116

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

前面的代碼中我們創(chuàng)建了一個lambda表達式,作為forEach方法的入?yún)ⅰK皇呛唵蔚匕褏?shù)傳給了一個println()方法。由于這個操作很常見,我們可以借助Java編譯器來對這段代碼進行簡化。就像在25頁的使用方法引用中那樣,用一個方法引用來代替它,讓編譯器來幫我們做參數(shù)路由。

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

復制代碼 代碼如下:

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

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

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

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

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

復制代碼 代碼如下:

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

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

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

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

w
0
0
t

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

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

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

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

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

0
0

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

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

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

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

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

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

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

相關文章

  • 基于HTTP協(xié)議實現(xiàn)簡單RPC框架的方法詳解

    基于HTTP協(xié)議實現(xiàn)簡單RPC框架的方法詳解

    RPC全名(Remote?Procedure?Call),翻譯過來就是遠程過程調(diào)用,本文將為大家介紹如何基于HTTP協(xié)議實現(xiàn)簡單RPC框架,感興趣的小伙伴可以了解一下
    2023-06-06
  • 深入理解Java編程線程池的實現(xiàn)原理

    深入理解Java編程線程池的實現(xiàn)原理

    這篇文章主要介紹了深入理解Java編程線程池的實現(xiàn)原理,涉及ThreadPoolExecutor類,線程池實現(xiàn)原理及示例等相關內(nèi)容,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • logback如何去掉DubboMonitor煩人的INFO日志

    logback如何去掉DubboMonitor煩人的INFO日志

    這篇文章主要介紹了logback如何去掉DubboMonitor煩人的INFO日志方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • java正則表達式的應用 java讀取文件并獲取電話號碼

    java正則表達式的應用 java讀取文件并獲取電話號碼

    這篇文章主要介紹了java正則表達式的應用,應用的內(nèi)容是java讀取文件并獲取電話號碼,感興趣的小伙伴們可以參考一下
    2015-11-11
  • Idea 快速生成方法返回值的操作

    Idea 快速生成方法返回值的操作

    這篇文章主要介紹了Idea 快速生成方法返回值的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • Mybatis如何按順序查詢出對應的數(shù)據(jù)字段

    Mybatis如何按順序查詢出對應的數(shù)據(jù)字段

    這篇文章主要介紹了Mybatis如何按順序查詢出對應的數(shù)據(jù)字段,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • MyBatis中傳入?yún)?shù)parameterType類型詳解

    MyBatis中傳入?yún)?shù)parameterType類型詳解

    這篇文章主要給大家介紹了關于MyBatis中傳入?yún)?shù)parameterType類型的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2018-04-04
  • Java服務端如何解決跨域問題?CORS請求頭方式

    Java服務端如何解決跨域問題?CORS請求頭方式

    這篇文章主要介紹了Java服務端如何解決跨域問題?CORS請求頭方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • Springboot中的@ConditionalOnBean注解詳細解讀

    Springboot中的@ConditionalOnBean注解詳細解讀

    這篇文章主要介紹了Springboot中的@ConditionalOnBean注解詳細解讀,@ConditionalOnMissingBean注解兩個類,一個Computer類,一個配置類,想要完成;如果容器中沒有Computer類,就注入備用電腦Computer類,如果有Computer就不注入,需要的朋友可以參考下
    2023-11-11
  • Java使用動態(tài)規(guī)劃算法思想解決背包問題

    Java使用動態(tài)規(guī)劃算法思想解決背包問題

    背包問題(Knapsack problem)是一種組合優(yōu)化的NP完全問題。問題可以描述為:給定一組物品,每種物品都有自己的重量和價格,在限定的總重量內(nèi),我們?nèi)绾芜x擇,才能使得物品的總價格最高
    2022-04-04

最新評論