一篇文章帶你了解Java Stream流
一、Stream流引入
Lambda表達(dá)式,基于Lambda所帶來(lái)的函數(shù)式編程,又引入了一個(gè)全新的Stream概念,用于解決集合類(lèi)庫(kù)既有的鼻端。(Lambda表達(dá)式詳解在上篇博客內(nèi)容)
現(xiàn)有一個(gè)需求:
將list集合中姓張的元素過(guò)濾到一個(gè)新的集合中
然后將過(guò)濾出來(lái)的姓張的元素中,再過(guò)濾出來(lái)長(zhǎng)度為3的元素,存儲(chǔ)到一個(gè)新的集合中
1.用常規(guī)方法解決需求
// 已知的知識(shí)來(lái)解決需求 List<String> list1 = new ArrayList<>(); list1.add("張老三"); list1.add("張小三"); list1.add("李四"); list1.add("趙五"); list1.add("張六"); list1.add("王八"); ArrayList<String> list2 = new ArrayList<>(); // 1.將list集合中姓張的元素過(guò)濾到一個(gè)新的集合中 for(String name : list1){ if(name.startsWith("張")){ list2.add(name); } } ArrayList list3 = new ArrayList(); for (String name : list2) { if (name.length() == 3){ list3.add(name); } } System.out.println(list3);
輸出結(jié)果:
[張顏宇, 張三豐]
2.用Stream流操作集合,獲取流,過(guò)濾操作,打印輸出
list1.stream().filter((String name)->name.startsWith("張")).filter((String name)->name.length()==3).forEach((String name)->{ System.out.println("符合條件的姓名:" + name); });
( 看不懂沒(méi)關(guān)系,下面會(huì)講到該方法,這里只是用來(lái)引入的)
二、Stream流的格式
Stream<T> filter(Predicate<? super T> predicate); -----> 參數(shù):public interface Predicate<T> (函數(shù)式接口) ----> 抽象方法:boolean test(T t); -----> 參數(shù):public interface Consumer<T> (函數(shù)式接口) ----> 抽象方法:boolean test(T t);
整體代碼看來(lái):流式思想 類(lèi)似于 工廠(chǎng)車(chē)間的“流水線(xiàn)”
( 看不懂沒(méi)關(guān)系,下面會(huì)講到該方法,這里只是用來(lái)引入的)
三、獲取流
根據(jù)集合來(lái)獲?。?/p>
根據(jù)Collection獲取流:
Collection接口中有一個(gè)stream()方法,可以獲取流
default Stream<E> stream()
1.根據(jù)List獲取流
2.根據(jù)Set獲取流
3.根據(jù)Map獲取流
3.1根據(jù)Map集合的鍵來(lái)獲取流
3.2根據(jù)Map集合的值獲取流
3.3根據(jù)Map集合的鍵值對(duì)對(duì)象獲取流
4.根據(jù)數(shù)組獲取流
代碼演示:
1.根據(jù)List集合獲取流
// 創(chuàng)建List集合 List<String> list = new ArrayList<>(); list.add("張老三"); list.add("張小三"); list.add("李四"); list.add("趙五"); list.add("張六"); list.add("王八"); Stream<String> stream1 = list.stream();
2.根據(jù)Set集合獲取流
// 創(chuàng)建List集合 Set<String> set = new HashSet<>(); list.add("張老三"); list.add("張小三"); list.add("李四"); list.add("趙五"); list.add("張六"); list.add("王八"); Stream<String> stream2 = set.stream();
3.根據(jù)Map集合獲取流
// 創(chuàng)建Map集合 Map<Integer,String> map = new HashMap<>(); map.put(1,"張老三"); map.put(2,"張小三"); map.put(3,"李四"); map.put(4,"趙五"); map.put(5,"張六"); map.put(6,"王八"); // 3.1根據(jù)Map集合的鍵獲取流 Set<Integer> map1 = map.keySet(); Stream<Integer> stream3 = map1.stream(); // 3.2根據(jù)Map集合的值獲取流 Collection<String> map2 = map.values(); Stream<String> stream4 = map2.stream(); // 3.3根據(jù)Map集合的鍵值對(duì)對(duì)象獲取瑞 Set<Map.Entry<Integer, String>> map3 = map.entrySet(); Stream<Map.Entry<Integer, String>> stream5 = map3.stream();
4.根據(jù)數(shù)組獲取流
// 根據(jù)數(shù)組獲取流 String[] arr = {"張顏宇","張三","李四","趙五","劉六","王七"}; Stream<String> stream6 = Stream.of(arr);
四、Stream流的常用方法
Stream流的常用方法:
終結(jié)方法:返回值類(lèi)型不再是Stream接口本身類(lèi)型的方法,例如:forEach方法和count方法
非終結(jié)方法/延遲方法:返回值類(lèi)型仍然是Stream接口自身類(lèi)型的方法,除了終結(jié)方法都是延遲方法。例如:filter,limit,skip,map,conat
方法名稱(chēng)方法作用方法種類(lèi)是否支持鏈?zhǔn)秸{(diào)用count統(tǒng)計(jì)個(gè)數(shù)終結(jié)方法否forEach逐一處理終結(jié)方法否filter過(guò)濾函數(shù)拼接是limit取用前幾個(gè)函數(shù)拼接是skip跳過(guò)前幾個(gè)函數(shù)拼接是map映射函數(shù)拼接是concat組合函數(shù)拼接是
方法演示:
1.count方法:
long count (); 統(tǒng)計(jì)流中的元素,返回long類(lèi)型數(shù)據(jù)
List<String> list = new ArrayList<>(); list.add("張老三"); list.add("張小三"); list.add("李四"); list.add("趙五"); list.add("張六"); list.add("王八"); long count = list.stream().count(); System.out.println("集合中的元素個(gè)數(shù)是:" + count);
輸出結(jié)果:
集合中的元素個(gè)數(shù)是:6
2.filter方法:
Stream<T> filter(Predicate<? super ?> predicate); 過(guò)濾出滿(mǎn)足條件的元素
參數(shù)Predicate:函數(shù)式接口,抽象方法:boolean test (T t)
Predicate接口:是一個(gè)判斷接口
// 獲取stream流 Stream<String> stream = Stream.of("張老三", "張小三", "李四", "趙五", "劉六", "王七"); // 需求:過(guò)去出姓張的元素 stream.filter((String name)->{ return name.startsWith("張"); }).forEach((String name)->{ System.out.println("流中的元素" + name); });
(上面引入Stream流時(shí),就用到了這個(gè)方法)
3.forEach方法
void forEach(Consumer<? super T> action):逐一處理流中的元素
參數(shù) Consumer<? super T> action:函數(shù)式接口,只有一個(gè)抽象方法:void accept(T t);
注意:
1.此方法并不保證元素的逐一消費(fèi)動(dòng)作在流中是有序進(jìn)行的(元素可能丟失)
2.Consumer是一個(gè)消費(fèi)接口(可以獲取流中的元素進(jìn)行遍歷操作,輸出出去),可以使用Lambda表達(dá)式
List<String> list = new ArrayList<>(); list.add("張老三"); list.add("張小三"); list.add("李四"); list.add("趙五"); list.add("張六"); list.add("王八"); // 函數(shù)模型:獲取流 --> 注意消費(fèi)流中的元素 list.stream().forEach((String name)->{ System.out.println(name); });
輸出結(jié)果:
張老三
張小三
李四
趙五
張六
王八
4.limit方法
Stream<T> limit(long maxSize); 取用前幾個(gè)元素
注意:
參數(shù)是一個(gè)long 類(lèi)型,如果流的長(zhǎng)度大于參數(shù),則進(jìn)行截取;否則不進(jìn)行操作
// 獲取流的長(zhǎng)度 Stream<String> stream1 = Stream.of("張老三", "張小三", "李四", "趙五", "劉六", "王七"); // 需求:保留前三個(gè)元素 stream1.limit(3).forEach((String name)->{ System.out.println("流中的前三個(gè)元素是:" + name); });
輸出結(jié)果:
流中的前三個(gè)元素是:張老三
流中的前三個(gè)元素是:張小三
流中的前三個(gè)元素是:李四
5.map方法
<r> Stream <R> map(Function<? super T,? exception R> mapper;
參數(shù)Function<T,R>:函數(shù)式接口,抽象方法:R apply(T t);
Function<T,R>:其實(shí)就是一個(gè)類(lèi)型轉(zhuǎn)換接口(T和R的類(lèi)型可以一致,也可以不一致)
// 獲取Stream流 Stream<String> stream1 = Stream.of("11","22","33","44","55"); // 需求:把stream1流中的元素轉(zhuǎn)換為int類(lèi)型 stream1.map((String s)->{ return Integer.parseInt(s); // 將String類(lèi)型的s進(jìn)行轉(zhuǎn)換為Integer類(lèi)型的元素,并返回 }).forEach((Integer i)->{ System.out.println(i); // 將轉(zhuǎn)換后的int類(lèi)型的元素逐一輸出 });
輸出結(jié)果:
11
22
33
44
55
6.skip方法
Stream<T> skip(long n); 跳過(guò)前幾個(gè)元素
注意:
如果流的當(dāng)前長(zhǎng)度大于n,則跳過(guò)前n個(gè),否則將會(huì)得到一個(gè)長(zhǎng)度為0的空流
// 獲取stream流 Stream<String> stream = Stream.of("張老三", "張小三", "李四", "趙五", "劉六", "王七"); stream.skip(3).forEach((String name)->{ System.out.println("跳過(guò)前三個(gè),打印剩下的" + name); });
輸出結(jié)果:
跳過(guò)前三個(gè),打印剩下的趙五
跳過(guò)前三個(gè),打印剩下的劉六
跳過(guò)前三個(gè),打印剩下的王七
7.concat方法
public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
--> 合并兩個(gè)流
Stream<String> stream1 = Stream.of("11","22","33","44","55"); Stream<String> stream2 = Stream.of("張顏宇", "張三", "李四", "趙五", "劉六", "王七"); // 需求:合并兩個(gè)流 Stream<String> stream = Stream.concat(stream1,stream2); stream.forEach((String name)->{ System.out.print(name); });
輸出結(jié)果:
1122334455張顏宇張三李四趙五劉六王七
五、收集Stream流
Stream流中提供了一個(gè)方法,可以把流中的數(shù)據(jù)收集到單例集合中
<R, A> R collect(Collector<? super T, A, R> collector); 把流中的數(shù)據(jù)手機(jī)到單列集合中
返回值類(lèi)型是R。R指定為什么類(lèi)型,就是手機(jī)到什么類(lèi)型的集合
參數(shù)Collector<? super T, A, R>中的R類(lèi)型,決定把流中的元素收集到哪個(gè)集合中
參數(shù)Collector如何得到 ?,可以使用 java.util.stream.Collectors工具類(lèi)中的靜態(tài)方法:
- public static <T> Collector<T, ?, List<T>> toList():轉(zhuǎn)換為L(zhǎng)ist集合
- public static <T> Collector<T, ?, Set<T>> toSet() :轉(zhuǎn)換為Set集合
List<String> list2 = new ArrayList<>(); list2.add("張老三"); list2.add("張小三"); list2.add("李四"); list2.add("趙五"); list2.add("張六"); list2.add("王八"); // 需求:過(guò)濾出姓張的并且長(zhǎng)度為3的元素 Stream<String> stream = list2.stream().filter((String name) -> { return name.startsWith("張"); }).filter((String name) -> { return name.length() == 3; }); // stream 收集到單列集合中 List<String> list = stream.collect(Collectors.toList()); System.out.println(list); // stream 手機(jī)到單列集合中 Set<String> set = stream.collect(Collectors.toSet()); System.out.println(set);
總結(jié)
本片文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
JavaWeb項(xiàng)目部署到服務(wù)器詳細(xì)步驟詳解
這篇文章主要介紹了JavaWeb項(xiàng)目如何部署到服務(wù)器,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04Java Web項(xiàng)目中使用Socket通信多線(xiàn)程、長(zhǎng)連接的方法
很多時(shí)候在javaweb項(xiàng)目中我們需要用到Socket通信來(lái)實(shí)現(xiàn)功能,在web中使用Socket我們需要建立一個(gè)監(jiān)聽(tīng)程序,在程序啟動(dòng)時(shí),啟動(dòng)socket監(jiān)聽(tīng)。接下來(lái)通過(guò)本文給大家介紹Java Web項(xiàng)目中使用Socket通信多線(xiàn)程、長(zhǎng)連接的方法,感興趣的朋友一起學(xué)習(xí)2016-04-04使用webservice自定義注解處理參數(shù)加解密問(wèn)題
這篇文章主要介紹了使用webservice自定義注解處理參數(shù)加解密問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Java 在volatile內(nèi)部調(diào)用接口的方法
在Java中,volatile?關(guān)鍵字通常用于確保變量的可見(jiàn)性和有序性,而不是用來(lái)修飾接口或方法調(diào)用的,這篇文章主要介紹了Java 在volatile內(nèi)部調(diào)用接口的方法,需要的朋友可以參考下2024-07-07SpringBoot自動(dòng)配置與啟動(dòng)流程詳細(xì)分析
這篇文章主要介紹了SpringBoot自動(dòng)配置原理分析,SpringBoot是我們經(jīng)常使用的框架,那么你能不能針對(duì)SpringBoot實(shí)現(xiàn)自動(dòng)配置做一個(gè)詳細(xì)的介紹。如果可以的話(huà),能不能畫(huà)一下實(shí)現(xiàn)自動(dòng)配置的流程圖。牽扯到哪些關(guān)鍵類(lèi),以及哪些關(guān)鍵點(diǎn)2022-11-11