詳解Java8?StreamAPI中的map()方法
Stream API 是Java8中新加入的功能,現(xiàn)在都 Java20 了,不會(huì)還有人沒用過吧?
今天給大家演示一下 Stream API 中的 map() 方法。
前言
在日常的開發(fā)工作中經(jīng)常碰到要處理 List 中數(shù)據(jù)的問題,比如從一個(gè)對象集合中獲得對象中的一個(gè)屬性的集合。之前我們想到的是遍歷每個(gè)元素,然后取出來放到另外一個(gè)集合中,比較繁瑣;在 Java8 之后,對集合可以進(jìn)行 Stream 操作,使上面的處理更簡潔。
概述
Stream 流式處理中有 map() 方法,先看下其定義,該方法在java.util.stream.Stream類中
可以看到 map() 方法接收一個(gè)函數(shù)式接口參數(shù),入?yún)⒂幸粋€(gè) T ,返回一個(gè) Stream 流,這個(gè)流是 R 泛型。主要有以下幾點(diǎn)注意,
- 入?yún)⑹且粋€(gè)流中的元素;
- 出參是一個(gè)流,且流中是新元素;
用圖表示就是下面的樣子,原始流中有四個(gè)圓形圖案,調(diào)用 map() 函數(shù)后變成了四個(gè)五角星圖案,這里的圓形圖案和五角星圖案是一一對應(yīng)的,也就是原始流中有多少個(gè)元素,調(diào)用 map() 方法后依舊有多少個(gè)元素,唯一改變的是流中的元素類型。
示例
我們先創(chuàng)建一個(gè)實(shí)體類 Student.java
@Data public?class?Student?implements?Serializable?{ ????/** ?????*?姓名 ?????*/ ????private?String?name; ????/** ?????*?班級(jí) ?????*/ ????private?String?schoolClass; ????/** ?????*語文成績 ?????*/ ????private?Integer?chineseScore; ????/** ?????*?數(shù)學(xué)成績 ?????*/ ????private?Integer?mathScore; }
再創(chuàng)建一個(gè)初始化數(shù)據(jù)的類:
public?class?DataFactory?{ ????public?static?List<Student>?initData(){ ????????List<Student>?list=?new?ArrayList<>(); ????????Student?s1=new?Student(); ????????s1.setName("湯霖"); ????????s1.setSchoolClass("小一班"); ????????s1.setChineseScore(87); ????????s1.setMathScore(95); ????????list.add(s1); ? ????????Student?s2=new?Student(); ????????s2.setName("李牧唐"); ????????s2.setSchoolClass("小二班"); ????????s2.setChineseScore(98); ????????s2.setMathScore(97); ????????list.add(s2); ? ????????Student?s3=new?Student(); ????????s3.setName("顧北辰"); ????????s3.setSchoolClass("二年級(jí)"); ????????s3.setChineseScore(89); ????????s3.setMathScore(94); ????????list.add(s3); ? ????????Student?s4=new?Student(); ????????s4.setName("言言"); ????????s4.setSchoolClass("小二班"); ????????s4.setChineseScore(100); ????????s4.setMathScore(90); ????????list.add(s4); ? ????????Student?s5=new?Student(); ????????s5.setName("大運(yùn)"); ????????s5.setSchoolClass("小三班"); ????????s5.setChineseScore(96); ????????s5.setMathScore(100); ????????list.add(s5); ????????return?list; ????} }
找出所有的學(xué)生姓名
public?static?void?main(String[]?args)?{ ??? DataFactory.initData().stream() ????????.map(student?->?student.getName()) ????????.forEach(System.out::println); }
這里使用了 map() 方法,入?yún)⑹?Student,出參是以 String 為泛型的流,最后使用 forEach 進(jìn)行了打印,看下結(jié)果
可以看到剛好把所有的學(xué)生姓名均打印出來了。如果想把這些學(xué)生姓名放到一個(gè)List中怎么辦?
將學(xué)生姓名放到list中
public?static?void?main(String[]?args)?{ ????//將所有的學(xué)生姓名放到list中 ????List<String>?studentNames = DataFactory.initData().stream() ????????.map(student?->?student.getName()) ????????.collect(Collectors.toList()); ????for?(String?studentName : studentNames)?{ ????????System.out.println(studentName); ????} }
同樣的找出所有的班級(jí),找出所有學(xué)生的成績都可類比上面的,可以看到打印出的學(xué)生姓名或班級(jí)是有重復(fù)數(shù)據(jù),這個(gè)要怎么解決。我們知道在最后是把數(shù)據(jù)放到 List 中,為了解決重復(fù)的問題可以把數(shù)據(jù)放到 Set 中,利用 Set 的去重功能:
//將學(xué)生姓名放到Set中,可以實(shí)現(xiàn)去重功能 Set<String>?studentNames = DataFactory.initData().stream() ????.map(student?->?student.getName()) ????.collect(Collectors.toSet());
結(jié)果不再打印,有興趣的可以自己試試。
將姓名為“湯霖”的語文成績置為90
現(xiàn)在有這樣一個(gè)需求,要把姓名為湯霖學(xué)生的語文成績置為90
,看下利用 map() 函數(shù)怎么做?
public?static?void?main(String[]?args)?{ ????List<Student>?students?=?DataFactory.initData(); ????List<Student>?studentNames?=?students.stream().map(student?->?{ ????????if?("湯霖".equals(student.getName()))?{ ????????????student.setChineseScore(90); ????????} ????????return?student; ????}).collect(Collectors.toList()); ????for?(Student?studentName?:?studentNames)?{ ????????System.out.println(studentName); ????} ????//打印老的list ????System.out.println("-----改之前的數(shù)據(jù)-----"); ????for?(Student?studentName?:?students)?{ ????????System.out.println(studentName); ????} }
輸出結(jié)果:
從上面的結(jié)果中可以看出,湯霖的語文成績的確被改為了90
,這點(diǎn)是沒錯(cuò)的。再看原數(shù)據(jù)也被改為了90
,上面提到過 map() 方法生成的是一個(gè)新流,原始流中的數(shù)據(jù)也被修改了,因?yàn)橄旅孢@行代碼是在原始流中元素的基礎(chǔ)上修改的引用類型中的數(shù)據(jù),導(dǎo)致的原始流中的數(shù)據(jù)也會(huì)改。
總結(jié)
Java8 的 Stream 流 map() 方法是將流中的元素轉(zhuǎn)換為另外一個(gè)流中的元素,轉(zhuǎn)換前后兩個(gè)流的元素個(gè)數(shù)不發(fā)生改變。
到此這篇關(guān)于詳解Java8 StreamAPI中的map()方法的文章就介紹到這了,更多相關(guān)Java8 StreamAPI map內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java?線程池狀態(tài)及狀態(tài)轉(zhuǎn)換
這篇文章主要介紹了java?線程池狀態(tài)及狀態(tài)轉(zhuǎn)換,Java里線程池的狀態(tài)和線程的狀態(tài)是完全不同的,具體有幾種狀態(tài)和哪些不同點(diǎn),下面文章詳細(xì)介紹,需要的小伙伴可以參考一下2022-05-05Springboot項(xiàng)目編譯后未能加載靜態(tài)資源文件的問題
這篇文章主要介紹了Springboot項(xiàng)目編譯后未能加載靜態(tài)資源文件的問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08Mybatis?Interceptor線程安全引發(fā)的bug問題
這篇文章主要介紹了Mybatis?Interceptor線程安全引發(fā)的bug問題及解決,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02創(chuàng)建動(dòng)態(tài)代理對象bean,并動(dòng)態(tài)注入到spring容器中的操作
這篇文章主要介紹了創(chuàng)建動(dòng)態(tài)代理對象bean,并動(dòng)態(tài)注入到spring容器中的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02Java源碼深度分析String與StringBuffer及StringBuilder詳解
當(dāng)對字符串進(jìn)行修改的時(shí)候,需要使用?StringBuffer?和?StringBuilder類,和String類不同的是,StringBuffer和?StringBuilder類的對象能夠被多次的修改,并且不產(chǎn)生新的未使用對象,本篇我們來分析分析它們的源碼2022-05-05RocketMQ消息生產(chǎn)者是如何選擇Broker示例詳解
這篇文章主要為大家介紹了RocketMQ消息生產(chǎn)者是如何選擇Broker示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11Java中Easypoi實(shí)現(xiàn)excel多sheet表導(dǎo)入導(dǎo)出功能
這篇文章主要介紹了Java中Easypoi實(shí)現(xiàn)excel多sheet表導(dǎo)入導(dǎo)出功能,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01SpringBoot中讀取jar包中的resources目錄下的文件的三種方式
這篇文章給大家總結(jié)了SpringBoot讀取 jar 包中的 resources 目錄下的文件的三種方式,文中有詳細(xì)的代碼示例供大家參考,,需要的朋友可以參考下2023-06-06