jdk1.8 lambda表達式的用法

Lambda 表達式的結(jié)構(gòu)

讓我們了解一下 Lambda 表達式的結(jié)構(gòu)蛔垢。

一個 Lambda 表達式可以有零個或多個參數(shù)

參數(shù)的類型既可以明確聲明,也可以根據(jù)上下文來推斷掘而。例如:(int a)與(a)效果相同

所有參數(shù)需包含在圓括號內(nèi)挟冠,參數(shù)之間用逗號相隔。例如:(a, b)或(int a, int b)或(String a, int b, float c)

空圓括號代表參數(shù)集為空袍睡。例如:() -> 42

當(dāng)只有一個參數(shù)知染,且其類型可推導(dǎo)時,圓括號()可省略斑胜。例如:a -> return a*a

Lambda 表達式的主體可包含零條或多條語句

如果 Lambda 表達式的主體只有一條語句控淡,花括號{}可省略。匿名函數(shù)的返回類型與該主體表達式一致

如果 Lambda 表達式的主體包含一條以上語句止潘,則表達式必須包含在花括號{}中(形成代碼塊)掺炭。匿名函數(shù)的返回類型與代碼塊的返回類型一致,若沒有返回則為空

什么是函數(shù)式接口

在 Java 中凭戴,Marker(標(biāo)記)類型的接口是一種沒有方法或?qū)傩月暶鞯慕涌诮ǎ唵蔚卣f,marker 接口是空接口。相似地勋篓,函數(shù)式接口是只包含一個抽象方法聲明的接口吧享。

java.lang.Runnable就是一種函數(shù)式接口,在 Runnable 接口中只聲明了一個方法void run()譬嚣,相似地,ActionListener 接口也是一種函數(shù)式接口钞它,我們使用匿名內(nèi)部類來實例化函數(shù)式接口的對象拜银,有了 Lambda 表達式,這一方式可以得到簡化遭垛。

每個 Lambda 表達式都能隱式地賦值給函數(shù)式接口尼桶,例如,我們可以通過 Lambda 表達式創(chuàng)建 Runnable 接口的引用锯仪。

Runnable r = () -> System.out.println("hello world");

當(dāng)不指明函數(shù)式接口時泵督,編譯器會自動解釋這種轉(zhuǎn)化:

new Thread(

? () -> System.out.println("hello world")

).start();

因此,在上面的代碼中庶喜,編譯器會自動推斷:根據(jù)線程類的構(gòu)造函數(shù)簽名public Thread(Runnable r) { }小腊,將該 Lambda 表達式賦給 Runnable 接口。

以下是一些 Lambda 表達式及其函數(shù)式接口:?

Consumer? c = (int x) -> { System.out.println(x) };

BiConsumer b = (Integer x, String y) -> System.out.println(x + " : " + y);

Predicate p = (String s) -> { s == null };

@FunctionalInterface是 Java 8 新加入的一種接口久窟,用于指明該接口類型聲明是根據(jù) Java 語言規(guī)范定義的函數(shù)式接口秩冈。Java 8 還聲明了一些 Lambda 表達式可以使用的函數(shù)式接口,當(dāng)你注釋的接口不是有效的函數(shù)式接口時斥扛,可以使用 @FunctionalInterface 解決編譯層面的錯誤入问。

以下是一種自定義的函數(shù)式接口:

? ? @FunctionalInterface

? ? public interface WorkerInterface {

? public void doSomeWork();

}

根據(jù)定義,函數(shù)式接口只能有一個抽象方法稀颁,如果你嘗試添加第二個抽象方法芬失,將拋出編譯時錯誤。例如:

@FunctionalInterface

public interface WorkerInterface {

? ? public void doSomeWork();

? ? public void doSomeMoreWork();

}

錯誤:

Unexpected @FunctionalInterface annotation

? ? @FunctionalInterface ^ WorkerInterface is not a functional interface multiple

? ? non-overriding abstract methods found in interface WorkerInterface 1 error

函數(shù)式接口定義好后匾灶,我們可以在 API 中使用它棱烂,同時利用 Lambda 表達式。例如:

//定義一個函數(shù)式接口@FunctionalInterfacepublic interface WorkerInterface {? public void doSomeWork();}public class WorkerInterfaceTest {public static void execute(WorkerInterface worker) {? ? worker.doSomeWork();}public static void main(String [] args) {? ? //invoke doSomeWork using Annonymous class? ? execute(new WorkerInterface() {? ? ? ? @Override? ? ? ? public void doSomeWork() {? ? ? ? ? ? System.out.println("Worker invoked using Anonymous class");? ? ? ? }? ? });? ? //invoke doSomeWork using Lambdaexpression? ? execute( () -> System.out.println("Worker invoked using Lambda expression") );}}

輸出:

Worker invoked using Anonymous class

Worker invoked using Lambda expression

這上面的例子里粘昨,我們創(chuàng)建了自定義的函數(shù)式接口并與 Lambda 表達式一起使用垢啼。execute() 方法現(xiàn)在可以將 Lambda 表達式作為參數(shù)。

Lambda 表達式舉例

學(xué)習(xí) Lambda 表達式的最好方式是學(xué)習(xí)例子张肾。

線程可以通過以下方法初始化:

//舊方法:

new Thread(new Runnable() {

@Override

public void run() {

? ? System.out.println("Hello from thread");

}

}).start();

//新方法:

new Thread(

() -> System.out.println("Hello from thread")

).start();

以下代碼的作用是打印出給定數(shù)組中的所有元素芭析。注意,使用 Lambda 表達式的方法不止一種吞瞪。在下面的例子中馁启,我們先是用常用的箭頭語法創(chuàng)建 Lambda 表達式,之后,使用 Java 8 全新的雙冒號(::)操作符將一個常規(guī)方法轉(zhuǎn)化為 Lambda 表達式:

//Old way:

List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);

for(Integer n: list) {

? System.out.println(n);

}

//New way:

List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);

list.forEach(n -> System.out.println(n));

//or we can use :: double colon operator in Java 8

list.forEach(System.out::println);

下面的例子使用 Lambda 表達式打印數(shù)值中每個元素的平方惯疙,注意我們使用了 .stream() 方法將常規(guī)數(shù)組轉(zhuǎn)化為流翠勉。Java 8 增加了一些超棒的流 APIs。java.util.stream.Stream接口包含許多有用的方法霉颠,能結(jié)合 Lambda 表達式產(chǎn)生神奇的效果对碌。我們將 Lambda 表達式x -> x*x傳給 map() 方法,該方法會作用于流中的所有元素蒿偎。之后朽们,我們使用 forEach 方法打印數(shù)據(jù)中的所有元素:

//Old way:

List list = Arrays.asList(1,2,3,4,5,6,7);

for(Integer n : list) {

? ? int x = n * n;

? ? System.out.println(x);

}

//New way:

List list = Arrays.asList(1,2,3,4,5,6,7);

list.stream().map((x) -> x*x).forEach(System.out::println);

下面的例子會計算給定數(shù)值中每個元素平方后的總和。請注意诉位,Lambda 表達式只用一條語句就能達到此功能骑脱,這也是 MapReduce 的一個初級例子。我們使用 map() 給每個元素求平方苍糠,再使用 reduce() 將所有元素計入一個數(shù)值:

//Old way:

List list = Arrays.asList(1,2,3,4,5,6,7);

int sum = 0;

for(Integer n : list) {

? ? int x = n * n;

? ? sum = sum + x;

}

System.out.println(sum);

//New way:

List list = Arrays.asList(1,2,3,4,5,6,7);

int sum = list.stream().map(x -> x*x).reduce((x,y) -> x + y).get();

System.out.println(sum);

Lambda 表達式與匿名類的區(qū)別

使用匿名類與 Lambda 表達式的一大區(qū)別在于關(guān)鍵詞的使用叁丧。對于匿名類,關(guān)鍵詞this解讀為匿名類岳瞭,而對于 Lambda 表達式拥娄,關(guān)鍵詞this解讀為寫就 Lambda 的外部類。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末寝优,一起剝皮案震驚了整個濱河市条舔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌乏矾,老刑警劉巖孟抗,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異钻心,居然都是意外死亡凄硼,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門捷沸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來摊沉,“玉大人,你說我怎么就攤上這事痒给∷的” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵苍柏,是天一觀的道長尼斧。 經(jīng)常有香客問我,道長试吁,這世上最難降的妖魔是什么棺棵? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上烛恤,老公的妹妹穿的比我還像新娘母怜。我一直安慰自己,他們只是感情好缚柏,可當(dāng)我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布苹熏。 她就那樣靜靜地躺著,像睡著了一般船惨。 火紅的嫁衣襯著肌膚如雪柜裸。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天粱锐,我揣著相機與錄音,去河邊找鬼扛邑。 笑死怜浅,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蔬崩。 我是一名探鬼主播恶座,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼沥阳!你這毒婦竟也來了跨琳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤桐罕,失蹤者是張志新(化名)和其女友劉穎脉让,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體功炮,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡溅潜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了薪伏。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片滚澜。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖嫁怀,靈堂內(nèi)的尸體忽然破棺而出设捐,到底是詐尸還是另有隱情,我是刑警寧澤塘淑,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布萝招,位于F島的核電站,受9級特大地震影響朴爬,放射性物質(zhì)發(fā)生泄漏即寒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望母赵。 院中可真熱鬧逸爵,春花似錦、人聲如沸凹嘲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽周蹭。三九已至趋艘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間凶朗,已是汗流浹背瓷胧。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留棚愤,地道東北人搓萧。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像宛畦,于是被迫代替她去往敵國和親瘸洛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Java 8 lambda 表達式10個示例 Java 8 發(fā)布于4年前次和,日期是2014年3月18日反肋,這次開創(chuàng)性的...
    認真期待閱讀 1,385評論 2 6
  • lambda表達式(又被成為“閉包”或“匿名方法”)方法引用和構(gòu)造方法引用擴展的目標(biāo)類型和類型推導(dǎo)接口中的默認方法...
    183207efd207閱讀 1,483評論 0 5
  • 行為參數(shù)化 為了應(yīng)對多變的需求,難道我們就要因為客戶每提出一個需求踏施,我們就要寫一個方法去實現(xiàn)嗎石蔗? 顯然這樣做很冗余...
    uzip柚子皮閱讀 854評論 0 1
  • 原鏈接:http://www.cnblogs.com/langtianya/p/3757993.html JDK各...
    把愛放下會走更遠閱讀 1,112評論 0 10
  • 算法 算法的正式定義: 算法是定義一個可終止過程的一組無歧義的、可執(zhí)行的步驟的有序集合读规。 有步驟有順序是關(guān)鍵抓督。 不...
    BryantHe閱讀 524評論 0 2