日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

java里函数式表达式_Java8函数式编程 (一) 数据流和lambda表达式

發(fā)布時間:2025/3/21 java 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java里函数式表达式_Java8函数式编程 (一) 数据流和lambda表达式 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

JDK 1.8中引入了函數(shù)式編程(functional programming,FP),如果您已習(xí)慣OOP,一定會感到困惑:什么是函數(shù)式編程?這樣的編程模式有什么好處?

本文將通過簡單的實(shí)例令讀者對函數(shù)式編程有一個大體的了解。

我們知道OOP是以類為基礎(chǔ)的,程序中必須首先抽象和定義class。那么FP創(chuàng)建的基礎(chǔ)是什么?或者說在Java 8中,至少需要了解什么知識點(diǎn)才能實(shí)現(xiàn)基本的函數(shù)式編程呢?

本文將首先介紹在Java 8中使用FP所需的基本知識點(diǎn):Lambda表達(dá)式

數(shù)據(jù)流

基本實(shí)例Map>?phoneNumbers?=?new?HashMap>();phoneNumbers.put("Zhang?Jin",?Arrays.asList("3232312323",?"8933555472"));phoneNumbers.put("Li?Ming",?Arrays.asList("12323344",?"492648333"));phoneNumbers.put("Li?Guoping",?Arrays.asList("77323344",?"938448333"));Map>?filteredNumbers?=?phoneNumbers.entrySet().stream().filter(x?->?x.getKey().contains("Li")).collect(Collectors.toMap(p?->?p.getKey(),?p?->?p.getValue()));filteredNumbers.forEach((key,?value)?->?{System.out.println("Name:?"?+?key?+?":?");value.forEach(System.out::println);});

上半部分的代碼創(chuàng)建了一個從人名到此人所有電話號碼的Map,比較簡單,但接下來的部分對剛接觸Java 8的讀者不是一眼就能理解,我們一會兒來詳細(xì)解釋一下。

數(shù)據(jù)狀態(tài)不變原則

在分析上面的code前,先來看看FP與我們所熟知的OOP的最大不同。

在面向?qū)ο缶幊虝r,我們定義類和對象,并使用方法或表達(dá)式來執(zhí)行命令。這些方命令通常會改變程序的數(shù)據(jù)狀態(tài):Integer x = 0;x++;

比如上面的代碼,當(dāng)執(zhí)行x++后,x的值產(chǎn)生了變化,舊數(shù)據(jù)被新數(shù)據(jù)所取代。

相反,在函數(shù)式編程中,盡管我們也需要通過方法來執(zhí)行命令,但命令本身并不會改變程序已有的數(shù)據(jù)。簡單地說就是函數(shù)調(diào)用對外界不產(chǎn)生副作用,并總是輸出新的變量作為調(diào)用結(jié)果,比如下面的javascript:function max(a, b) {return a > b ? a : b;}var x = 10;var y = 5;var maximum = max(x, y);

此處max并不改變和依賴于外部的x和y,同時每次返回的結(jié)果都是一個全新的變量。

代碼分析

現(xiàn)在我們回到之前的代碼:// create a map, filter it by key valuesMap > filteredNumbers = phoneNumbers.entrySet().stream().filter(x -> x.getKey().contains("Li")).collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()));

這段代碼首先調(diào)用entrySet()來獲得phoneNumbers的entries集合,其中每個entry都由一個鍵值對組成。

接著,在得到的集合上調(diào)用stream()方法,該方法會創(chuàng)建一個數(shù)據(jù)流 (java.util.stream.Stream)。數(shù)據(jù)流(stream)是Java 8引入的新概念,參考Javadoc,可以將它理解為是一種可以在其上執(zhí)行順序或并行聚合操作的數(shù)據(jù)序列。這些操作可以包括過濾,修改,不同類型的轉(zhuǎn)換等。

得到stream后,代碼調(diào)用了filter(),filter通過給定的條件來過濾數(shù)據(jù)。此處的過濾條件是:x?->?x.getKey().contains("Li")

該處采用了Java 8引入的lambda表達(dá)式,我們可以把lambda表達(dá)式看成一個簡潔的匿名函數(shù),->左邊的x是輸入?yún)?shù),->右邊是需要執(zhí)行的命令。這里的lambda表達(dá)式又被稱作predicate,它是一個返回boolean類型的函數(shù),stream中的每個element都會被代入該predicate,通過運(yùn)算出的結(jié)果來決定是否在filter()重新返回的stream中被留下或移除。

下一個方法是collect(),可以看到,這里的方法調(diào)用都是鏈?zhǔn)降?#xff0c;原因在于這些方法都?xì)w屬于Stream接口,所以使用起來非常方便簡潔。

collect()方法的用途很簡單,它先從stream內(nèi)獲得數(shù)據(jù)(這里是java.util.Map.Entry),再將數(shù)據(jù)轉(zhuǎn)變成通常的java collection,比如List, Map, Set等數(shù)據(jù)結(jié)構(gòu)。這樣就重新將stream轉(zhuǎn)變成了我們所熟悉的類型。

Collection的遍歷

來看最后一部分代碼:filteredNumbers.forEach((key, value) -> {System.out.println("Name: " + key + ": ");value.stream().forEach(System.out::println);});

該代碼打印出所有的結(jié)果,但并沒有使用循環(huán),而是用了Java 8引入的forEach方法。

有了前面的基礎(chǔ),可以很容易看懂:forEach接收一個lambda表達(dá)式,filteredNumbers的每個element都講執(zhí)行該表達(dá)式。由于filteredNumbers是一個map,所以這里lambda表達(dá)式參數(shù)變成了key, value pair:// expression takes two parameters(key, value) - > {// print person’s nameSystem.out.println("Name: " + key + ": ");// iterate over the person’s phone numbers and print each of themvalue.forEach(System.out::println);}

由于value本身是一個List,所以又在其上調(diào)用了forEach。

至此代碼的輸出為:Name: Li Ming:12323344492648333Name: Li Guoping:77323344938448333

學(xué)到的知識點(diǎn) (以及問題)

本文表述的幾個關(guān)鍵點(diǎn):Java 8通過數(shù)據(jù)流和lambda表達(dá)式使函數(shù)式編程成為可能。

Lambda表達(dá)式和匿名函數(shù)十分相似。

Stream是一種可以在其上執(zhí)行順序或并行聚合操作的數(shù)據(jù)序列,這些操作會作用于序列里的每個元素。

函數(shù)式編程模式中的操作傾向于不依賴和不改變已有的數(shù)據(jù)狀態(tài)。

數(shù)據(jù)流操作很簡潔性 — 如果不考慮執(zhí)行效率的話。

但現(xiàn)在您可能會想:函數(shù)式編程寫出來的東西理解起來似乎更困難 — 我還是喜歡原來的寫法, 盡管它要啰嗦很多。

streams操作的執(zhí)行效率高嗎?

如果不改變數(shù)據(jù)狀態(tài),程序應(yīng)該怎么寫才好呢?

這些問題我會在后續(xù)的章節(jié)中進(jìn)一步討論,盡情期待。

本文出自 “Bug之家” 博客,轉(zhuǎn)載請與作者聯(lián)系!

總結(jié)

以上是生活随笔為你收集整理的java里函数式表达式_Java8函数式编程 (一) 数据流和lambda表达式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。