一、Stream流引入
Lambda表達式,基于Lambda所帶來的函數式編程,又引入了一個全新的Stream概念,用于解決集合類庫既有的鼻端。(Lambda表達式詳解在上篇博客內容)
現有一個需求:
將list集合中姓張的元素過濾到一個新的集合中
然后將過濾出來的姓張的元素中,再過濾出來長度為3的元素,存儲到一個新的集合中
1.用常規方法解決需求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// 已知的知識來解決需求 List<String> list1 = new ArrayList<>(); list1.add( "張老三" ); list1.add( "張小三" ); list1.add( "李四" ); list1.add( "趙五" ); list1.add( "張六" ); list1.add( "王八" ); ArrayList<String> list2 = new ArrayList<>(); // 1.將list集合中姓張的元素過濾到一個新的集合中 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); |
輸出結果:
[張顏宇, 張三豐]
2.用Stream流操作集合,獲取流,過濾操作,打印輸出
1
2
3
|
list1.stream().filter((String name)->name.startsWith( "張" )).filter((String name)->name.length()== 3 ).forEach((String name)->{ System.out.println( "符合條件的姓名:" + name); }); |
( 看不懂沒關系,下面會講到該方法,這里只是用來引入的)
二、Stream流的格式
1
2
3
4
5
|
Stream<T> filter(Predicate<? super T> predicate); -----> 參數: public interface Predicate<T> (函數式接口) ----> 抽象方法: boolean test(T t); -----> 參數: public interface Consumer<T> (函數式接口) ----> 抽象方法: boolean test(T t); |
整體代碼看來:流式思想 類似于 工廠車間的“流水線”
( 看不懂沒關系,下面會講到該方法,這里只是用來引入的)
三、獲取流
根據集合來獲取:
根據Collection獲取流:
Collection接口中有一個stream()方法,可以獲取流
default Stream<E> stream()
1.根據List獲取流
2.根據Set獲取流
3.根據Map獲取流
3.1根據Map集合的鍵來獲取流
3.2根據Map集合的值獲取流
3.3根據Map集合的鍵值對對象獲取流
4.根據數組獲取流
代碼演示:
1.根據List集合獲取流
1
2
3
4
5
6
7
8
9
|
// 創建List集合 List<String> list = new ArrayList<>(); list.add( "張老三" ); list.add( "張小三" ); list.add( "李四" ); list.add( "趙五" ); list.add( "張六" ); list.add( "王八" ); Stream<String> stream1 = list.stream(); |
2.根據Set集合獲取流
1
2
3
4
5
6
7
8
9
|
// 創建List集合 Set<String> set = new HashSet<>(); list.add( "張老三" ); list.add( "張小三" ); list.add( "李四" ); list.add( "趙五" ); list.add( "張六" ); list.add( "王八" ); Stream<String> stream2 = set.stream(); |
3.根據Map集合獲取流
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// 創建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根據Map集合的鍵獲取流 Set<Integer> map1 = map.keySet(); Stream<Integer> stream3 = map1.stream(); // 3.2根據Map集合的值獲取流 Collection<String> map2 = map.values(); Stream<String> stream4 = map2.stream(); // 3.3根據Map集合的鍵值對對象獲取瑞 Set<Map.Entry<Integer, String>> map3 = map.entrySet(); Stream<Map.Entry<Integer, String>> stream5 = map3.stream(); |
4.根據數組獲取流
1
2
3
|
// 根據數組獲取流 String[] arr = { "張顏宇" , "張三" , "李四" , "趙五" , "劉六" , "王七" }; Stream<String> stream6 = Stream.of(arr); |
四、Stream流的常用方法
Stream流的常用方法:
終結方法:返回值類型不再是Stream接口本身類型的方法,例如:forEach方法和count方法
非終結方法/延遲方法:返回值類型仍然是Stream接口自身類型的方法,除了終結方法都是延遲方法。例如:filter,limit,skip,map,conat
方法名稱方法作用方法種類是否支持鏈式調用count統計個數終結方法否forEach逐一處理終結方法否filter過濾函數拼接是limit取用前幾個函數拼接是skip跳過前幾個函數拼接是map映射函數拼接是concat組合函數拼接是
方法演示:
1.count方法:
long count (); 統計流中的元素,返回long類型數據
1
2
3
4
5
6
7
8
9
|
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( "集合中的元素個數是:" + count); |
輸出結果:
集合中的元素個數是:6
2.filter方法:
Stream<T> filter(Predicate<? super ?> predicate); 過濾出滿足條件的元素
參數Predicate:函數式接口,抽象方法:boolean test (T t)
Predicate接口:是一個判斷接口
1
2
3
4
5
6
7
8
|
// 獲取stream流 Stream<String> stream = Stream.of( "張老三" , "張小三" , "李四" , "趙五" , "劉六" , "王七" ); // 需求:過去出姓張的元素 stream.filter((String name)->{ return name.startsWith( "張" ); }).forEach((String name)->{ System.out.println( "流中的元素" + name); }); |
(上面引入Stream流時,就用到了這個方法)
3.forEach方法
void forEach(Consumer<? super T> action):逐一處理流中的元素
參數 Consumer<? super T> action:函數式接口,只有一個抽象方法:void accept(T t);
注意:
1.此方法并不保證元素的逐一消費動作在流中是有序進行的(元素可能丟失)
2.Consumer是一個消費接口(可以獲取流中的元素進行遍歷操作,輸出出去),可以使用Lambda表達式
1
2
3
4
5
6
7
8
9
10
11
|
List<String> list = new ArrayList<>(); list.add( "張老三" ); list.add( "張小三" ); list.add( "李四" ); list.add( "趙五" ); list.add( "張六" ); list.add( "王八" ); // 函數模型:獲取流 --> 注意消費流中的元素 list.stream().forEach((String name)->{ System.out.println(name); }); |
輸出結果:
張老三
張小三
李四
趙五
張六
王八
4.limit方法
Stream<T> limit(long maxSize); 取用前幾個元素
注意:
參數是一個long 類型,如果流的長度大于參數,則進行截取;否則不進行操作
1
2
3
4
5
6
|
// 獲取流的長度 Stream<String> stream1 = Stream.of( "張老三" , "張小三" , "李四" , "趙五" , "劉六" , "王七" ); // 需求:保留前三個元素 stream1.limit( 3 ).forEach((String name)->{ System.out.println( "流中的前三個元素是:" + name); }); |
輸出結果:
流中的前三個元素是:張老三
流中的前三個元素是:張小三
流中的前三個元素是:李四
5.map方法
<r> Stream <R> map(Function<? super T,? exception R> mapper;
參數Function<T,R>:函數式接口,抽象方法:R apply(T t);
Function<T,R>:其實就是一個類型轉換接口(T和R的類型可以一致,也可以不一致)
1
2
3
4
5
6
7
8
|
// 獲取Stream流 Stream<String> stream1 = Stream.of( "11" , "22" , "33" , "44" , "55" ); // 需求:把stream1流中的元素轉換為int類型 stream1.map((String s)->{ return Integer.parseInt(s); // 將String類型的s進行轉換為Integer類型的元素,并返回 }).forEach((Integer i)->{ System.out.println(i); // 將轉換后的int類型的元素逐一輸出 }); |
輸出結果:
11
22
33
44
55
6.skip方法
Stream<T> skip(long n); 跳過前幾個元素
注意:
如果流的當前長度大于n,則跳過前n個,否則將會得到一個長度為0的空流
1
2
3
4
5
|
// 獲取stream流 Stream<String> stream = Stream.of( "張老三" , "張小三" , "李四" , "趙五" , "劉六" , "王七" ); stream.skip( 3 ).forEach((String name)->{ System.out.println( "跳過前三個,打印剩下的" + name); }); |
輸出結果:
跳過前三個,打印剩下的趙五
跳過前三個,打印剩下的劉六
跳過前三個,打印剩下的王七
7.concat方法
public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
--> 合并兩個流
1
2
3
4
5
6
7
|
Stream<String> stream1 = Stream.of( "11" , "22" , "33" , "44" , "55" ); Stream<String> stream2 = Stream.of( "張顏宇" , "張三" , "李四" , "趙五" , "劉六" , "王七" ); // 需求:合并兩個流 Stream<String> stream = Stream.concat(stream1,stream2); stream.forEach((String name)->{ System.out.print(name); }); |
輸出結果:
1122334455張顏宇張三李四趙五劉六王七
五、收集Stream流
Stream流中提供了一個方法,可以把流中的數據收集到單例集合中
<R, A> R collect(Collector<? super T, A, R> collector); 把流中的數據手機到單列集合中
返回值類型是R。R指定為什么類型,就是手機到什么類型的集合
參數Collector<? super T, A, R>中的R類型,決定把流中的元素收集到哪個集合中
參數Collector如何得到 ?,可以使用 java.util.stream.Collectors工具類中的靜態方法:
- public static <T> Collector<T, ?, List<T>> toList():轉換為List集合
- public static <T> Collector<T, ?, Set<T>> toSet() :轉換為Set集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
List<String> list2 = new ArrayList<>(); list2.add( "張老三" ); list2.add( "張小三" ); list2.add( "李四" ); list2.add( "趙五" ); list2.add( "張六" ); list2.add( "王八" ); // 需求:過濾出姓張的并且長度為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 手機到單列集合中 Set<String> set = stream.collect(Collectors.toSet()); System.out.println(set); |
總結
本片文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注服務器之家的更多內容!
原文鏈接:https://blog.csdn.net/m0_60489526/article/details/119984236