程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java函數式編程(八):字符串及辦法援用

Java函數式編程(八):字符串及辦法援用

編輯:關於JAVA

Java函數式編程(八):字符串及辦法援用。本站提示廣大學習愛好者:(Java函數式編程(八):字符串及辦法援用)文章只能為提供參考,不一定能成為您想要的結果。以下是Java函數式編程(八):字符串及辦法援用正文


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

JDK引入的一些辦法對寫出函數式作風的代碼很有贊助。JDK庫裡的一些的類和接口我們曾經用得異常熟習了,好比說String,為了解脫之前習氣的那種老的作風,我們得自動尋覓機遇來應用這些新的辦法。異樣,當我們須要用到只要一個辦法的匿名外部類時,我們如今可以用lambda表達式來調換它了,不消再像本來那樣寫的那末繁瑣了。

本章我們會應用lambda表達式和辦法援用來遍歷字符串,完成Comparator接口,檢查目次中的文件,監督文件及目次的變革。上一章中引見的一些辦法還將持續湧現在這裡,來贊助我們更好的完成這些義務。你學到的這些新技巧有助於將冗雜繁瑣的代碼變得簡練,不只能疾速完成並且還易於保護。

遍歷字符串

chars()辦法是String類裡的一個新辦法,它是CharSequence接口的一部門。想要疾速遍歷String的字符序列的話,它是一個很有效的對象。有了這個外部迭代器,我們可以便利的操作字符串中的各個字符。先用它來處置一個字符串嘗嘗。在這裡趁便引見辦法援用的幾種應用方法。

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

chars()辦法前往的是一個Stream對象,我們可以用它的外部迭代器forEach()來停止遍歷。在迭代器裡,我們可以直接拜訪到字符串中的字符。上面是遍歷字符串並打印各個字符的輸入成果。

119
48
48
116

這其實不是我們想要的成果。我們願望看到的是字母,而輸入的倒是數字。這是由於chars()辦法前往的是一個整型的Stream而不是字符型的。我們先懂得下這個API,再去優化輸入的成果。

後面的代碼中我們創立了一個lambda表達式,作為forEach辦法的入參。它只是簡略地把參數傳給了一個println()辦法。因為這個操作很罕見,我們可以借助Java編譯器來對這段代碼停止簡化。就像在25頁的應用辦法援用中那樣,用一個辦法援用來取代它,讓編譯器來幫我們做參數路由。

我們曾經看到若何創立一個實例辦法的辦法援用了。好比,name.toUpperCase()辦法,辦法援用就是String::toUpperCase。而上面這個例子中,我們挪用的是靜態援用System.out的一個實例辦法。辦法援用的兩個冒號右邊,可所以一個類名或許表達式。有了這個靈巧性,我們可以很輕易創立一個println()辦法的援用,就像上面如許。

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

可以看到,Java編譯器能很聰慧的完成參數的路由。回憶下lambda表達式和辦法援用只能湧現在吸收函數式接口的處所,而Java編譯器會在誰人處所生成一個對應的辦法(譯注:編譯器會生成函數式接口的完成,這個完成只要一個辦法)。之前我們用過的辦法援用String::toUpperCase,傳給誰人生成辦法的參數,最初會釀成這個辦法挪用的目的對象,就像如許:parameter.toUpperCase()。這是由於這個辦法援用是基於類名的(String)。而下面這個例子中的辦法援用,是基於一個表達式的,它是PrintStream的一個實例,經由過程System.out來援用它。因為辦法挪用的對象曾經有了,Java編譯器決議用生成辦法中的參數作為這個println辦法的參數:System.out.println(name)。

(譯注:其實重要是兩種場景,異樣是傳遞了一個辦法援用,一個是把遍歷的對象,固然辦法挪用的目的對象,好比name.toUpperCase,別的一種是作為辦法挪用的參數,好比System.out.println(name).)

用了辦法援用以後代碼簡練多了,不外我們得去深刻懂得下它是若何運轉的。一旦我們熟習了辦法援用,就可以本身想明確參數路由這些事了。

雖然這個例子中的代碼曾經夠簡練的了,然則輸入照樣不如人意。我們想看到的是字母成果卻湧現了數字。為懂得決這個成績,我們來寫個辦法將int輸入成字母。

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

應用辦法援用可以很便利的完成輸入成果的優化。

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

如今固然chars()前往的成果是int,然則也無所謂了,須要打印的時刻,我們會將它轉化成字符。這回的輸入終究是字母了。

w
0
0
t

假如我們願望從一開端就處置的就是字符而不是int,可以在挪用完chars後直接將int轉化成字符:

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

這裡我們用到了chars()前往的Stream的一個外部迭代器,固然能用的可不止這一個辦法。拿到Stream對象後,它的那些辦法就職憑我們應用了,好比map(),filter(),reduce()等。我們可使用filter()辦法來過濾出那些是數字的字符:

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

如許輸入的時刻我們就只能看到數字了:

0
0

異樣的,除將lambda表達式傳給filter()和forEach()辦法外,我們還可使用辦法援用。

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

這裡的辦法援用把過剩的參數路由給免卻了。在本例中,我們還看到了和後面兩個辦法的援用分歧的用法。第一次我們援用的是一個實例辦法,第二次是一個靜態援用(System.out)上的辦法。而此次則是一個靜態辦法的援用——辦法援用一向在默默的支付。

實例辦法和靜態辦法的援用看起來都一樣:比喻說String::toUpperCase和Character::isDigit。編譯器會斷定辦法是實例辦法照樣靜態辦法,來決議若何路由參數。假如是實例辦法,它會將生成辦法的入參用作辦法挪用的目的對象,好比 parameter,toUpperCase();(固然也有破例,好比辦法挪用的目的對象曾經指定了,像System::out.println())。別的假如是靜態辦法的話,生成辦法的入參就會作為這個援用的辦法的參數,好比Character.isDigit(parameter)。152頁的附錄2,有具體的辦法援用的應用辦法及語法解釋。

雖然辦法援用用起來很便利,但還有一個成績——辦法定名抵觸招致的二義性 。假如婚配的辦法既有實例辦法也有靜態辦法,因為辦法存在歧義編譯器會報錯。好比這麼寫,Double::toString,我們實際上是想要把一個double類型轉化成字符串,但編譯器就不曉得究竟是該挪用public String toString()的實例辦法好,照樣去挪用public static String toString(double)辦法,由於兩個辦法都是Double類的。假如你碰著如許的情形,別洩氣,就用lambda表達式來完造詣好了。

一旦我們順應了函數式編程,我們便可以在lambda表達式和辦法援用之間為所欲為地往返切換了。

本節中我們用了Java 8中的一個新辦法來遍歷字符串。上面我們來看下Comparator接口又有了哪些改良。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved