網站首頁 編程語言 正文
Stream概述
Stream流是jdk1.8對集合對象功能的增強,可以通過將集合轉換為流模型,通過聲明的方式對集合中的每個元素進行一系列并行或者串行的流水線操作。
Stream只要給出對其包含的元素執行什么操作,Stream就會隱式地在內部進行遍歷,并給出響應的數據轉換。
Stream可以并行化操作,Stream的并行操作是依賴Java7中引入的Fork/Join框架拆分任務和加速處理過程,并且允許數據源是無限的。
基本的執行流程
使用Stream通常包括3個基本步驟:獲取數據源source -> 轉換為流 -> 執行操作 -> 獲取所想要的結果。每次轉換原有的Stream對象,執行結果還是Stream,可以使用串式寫法定義多個操作。
- 將
List<T>
集合轉換為Stream<T>
- 針對Stream進行一系列操作,每次操作結束返回還是Stream。
- 可以將Stream轉換回集合類型,也可以直接對其中的元素進行處理。
獲取Stream
流Stream既可以是串行順序的stream,也可以是并行的parallelStream。順序流的操作是在單線程上執行,而并行流是在多線程上并發執行的。
通過集合獲取
Arrays.stream(arr)
可以使用 Arrays.stream 將一組數據轉換為Stream。
Integer[] arr = new Integer[]{3,4,5,6,78,4};
long count = Arrays.stream(arr).filter(i -> i>20).count();
System.out.println("count=" + count);
輸出:
count=1
123456
list.stream()
使用Collection.parallelStream使用并行流,處理任務并行執行。
List<Integer> list = Arrays.asList(1,2,3,4,5,6);
Stream<Integer> stream = list.parallelStream();
stream.forEach(System.out::print);
System.out.println("\n++++++");
Stream<Integer> stream2 = list.stream();
stream2.forEach(System.out::print);
輸出:
456321
++++++
123456
123456789101112
parallelStream在使用上和stream沒有區別,本質上返回的都是一個流,只不過底層處理時會根據執行環境的條件判斷時并行還是串行。
Stream.of()
Integer[] arr = new Integer[]{3,4,5,6,78,4};
List<Integer> list = Arrays.asList(1,2,3,4,5,6);
Stream.of(arr).forEach(System.out::println);
Stream.of(list).forEach(System.out::println);
輸出:
3
4
5
6
78
4
[1, 2, 3, 4, 5, 6]
1234567891011121314
基本類型Stream
對于基本類型目前有3中對應的包裝類型Stream:IntStream
、LongStream
和 DoubleStream
。如果不使用對應的Stream類型,也可以使用 Stream、Stream 和 Stream ,但是針對元素進行裝拆箱操作比較耗時,所以才有了常用的基本數據類型的對應Stream。
//參數類型為int...不確定個數的參數,可以根據參數生成一個stream
IntStream.of(3,5,18,1,4).forEach(System.out::println);
//根據指定的返回生成一組連續值,1-10含左不含右
IntStream.range(1,10).forEach(System.out::println);
//根據指定的返回生成一組連續值,10-20含左含右
IntStream.rangeClosed(10,20).forEach(System.out::println);
12345678
從輸入流中獲取數據的方法
BufferedReader類方法lines()
返回Stream
BufferedReader br = new BufferedReader(new FileReader("data.txt"));
Stream<String> stream = br.lines();
stream.foreach(System.out::prinln);
123
轉換操作
Stream的操作符基本可以分為轉換操作和聚合操作兩大類,轉換操作符會繼續向下傳遞,聚合操作符直接對數據進行消費或者收集,不會繼續向下傳遞。
- 轉換操作操作符
-
map
:轉換操作符,用于映射每個元素到對應的結果 -
flatMap
:合并轉換 -
filter
:過濾操作,過濾滿足條件的數據 -
limit
:限流操作 -
skip
:跳過操作 -
distinct
:去重操作,底層采用equals進行比對 -
peek
:跳出操作 -
sorted
:排序操作,Comparable和Comparator接口
-
map
map
方法用于映射每個元素到對應的結果,轉換操作函數當做參數傳入方法。
List<Integer> list = new ArrayList<Integer>();
list.add(15);
list.add(32);
list.add(67);
list.add(232);
System.out.println(list);
//將Integer類型的元素映射轉換為String類型
List<String> result = list.stream().map(i -> String.valueOf(i)).collect(Collectors.toList());
System.out.println(result);
將Integer類型的元素映射轉換為String類型,再過濾字符串長度大于2的元素
List<String> result2 = list.stream().map(i -> String.valueOf(i)).filter(bb -> bb.length()>2).collect(Collectors.toList());
System.out.println(result2);
輸出:
[15, 32, 67, 232]
[15, 32, 67, 232]
[232]
123456789101112131415161718
mapToInt、mapToLong、mapToDouble
用于 統計 結果收集器產生統計結果值,主要用于int、long、double等基本類型。
List<Integer> nums = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = nums.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("最大值:"+stats.getMax());
System.out.println("最小值:"+stats.getMin());
System.out.println("所有數據之和:"+stats.getSum());
System.out.println("所有數據的平均值:"+stats.getAverage());
System.out.println("所有數據的個數:"+stats.getCount());
輸出:
最大值:7
最小值:2
所有數據之和:25
所有數據的平均值:3.5714285714285716
所有數據的個數:7
1234567891011121314
元素是類
HashSet<Product> products = new HashSet<>();
products.add(new Product("product1","11.2"));
products.add(new Product("product2","22.3"));
products.add(new Product("product3","33.4"));
double sum = products.stream().mapToDouble(v -> Double.valueOf(v.getPrice())).sum();
double max = products.stream().mapToDouble(v -> Double.valueOf(v.getPrice())).max().getAsDouble();
double min = products.stream().mapToDouble(v -> Double.valueOf(v.getPrice())).min().getAsDouble();
double average = products.stream().mapToDouble(v -> Double.valueOf(v.getPrice())).average().getAsDouble();
long count = products.stream().mapToDouble(v -> Double.valueOf(v.getPrice())).count();
System.out.println("最大值:"+ max);
System.out.println("最小值:"+ min);
System.out.println("所有數據之和:"+ sum);
System.out.println("所有數據的平均值:"+ average);
System.out.println("所有數據的個數:"+ count);
輸出:
最大值:33.4
最小值:11.2
所有數據之和:66.9
所有數據的平均值:22.3
所有數據的個數:3
1234567891011121314151617181920212223
注:
max()
、min()
、average()
獲取的是 OptionalDouble類型,需要調用getAsDouble()
返回double類型。
flatMap
flatMap
將多個流合并,比如,將List<List<String>>
通過flatMap函數可以變為List<String>
List<Integer> list1 = new ArrayList<>();
list1.add(34);
list1.add(25);
list1.add(35);
List<Integer> list2 = new ArrayList<>();
list2.add(999);
list2.add(888);
list2.add(999);
list2.add(666);
List<List<Integer>> tesList = new ArrayList<>();
tesList.add(list1);
tesList.add( list2);
List<Integer> result = tesList.stream()
.flatMap(num -> num.stream()).collect(Collectors.toList());
System.out.println(result);
輸出:
[34, 25, 35, 999, 888, 999, 666]
1234567891011121314151617181920
屬性合并
合并兩個 list< map >, 并將userId 相同的所有屬性合并到一個 map 中。
list1中對象的屬性:userId、userName
list2中對象的屬性:userId、gender、age
最總集合中對象的屬性:userId、userName、gender、age
public class MergeStream {
public static void main(String[] args) {
List<Map<String,Object>> list1 = new ArrayList<>();
Map<String,Object> data=new HashMap<>();
data.put("userId","100001");
data.put("userName","唐僧");
list1.add(data);
List<Map<String,Object>> list2 = new ArrayList<>();
data=new HashMap<>();
data.put("userId","100001");
data.put("gender","男");
data.put("age",20);
list2.add(data);
List<Map<String, Object>> collect = list1.stream().map(m1 -> {
list2.stream().filter(m2 -> m1.get("userId").equals(m2.get("userId"))).forEach(m2 -> {
m1.put("gender", m2.get("gender"));
m1.put("age", m2.get("age"));
});
return m1;
}).collect(Collectors.toList());
System.out.println(collect);
}
}
輸出:
[{gender=男, userName=唐僧, userId=100001, age=20}]
1234567891011121314151617181920212223242526272829
更多操作詳見:jdk8使用stream實現兩個list集合合并成一個(對象屬性的合并)
filter
filter
方法用于對傳入的數據流進行過濾處理,只返回滿足條件的數據組成的新的數據流。
List<Integer> list = new ArrayList<Integer>();
list.add(15);
list.add(32);
list.add(67);
list.add(232);
System.out.println(list);
List<Integer> result = list.stream().filter(i -> i>50).collect(Collectors.toList());
System.out.println(result);
輸出:
[15, 32, 67, 232]
[67, 232]
1234567891011121314
limit
limit
方法會返回一個包含指定個數元素的新stream,如果原始數據總長大小不足則返回原始流。
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < 10; i++) {
list.add(i);
}
List<Integer> result = list.stream().limit(5).collect(Collectors.toList());
System.out.println(result);
輸出:
[0, 1, 2, 3, 4]
1234567891011
skip方法
skip
方法的含義是跳過多少個元素,繼續處理后續元素。
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < 10; i++) {
list.add(i);
}
List<Integer> result2 = list.stream().skip(5).collect(Collectors.toList());
System.out.println(result2);
輸出:
[5, 6, 7, 8, 9]
1234567891011
distinct
distinct
會根據原始流中的元素返回一個具有相同順序,剔除了重復值的流。
List<Product> list = new ArrayList<Product>();
list.add(new Product("product1","11.2"));
list.add(new Product("product2","22.3"));
list.add(new Product("product3","33.4"));
list.add(new Product("product1","11.2"));
List<Product> list2 = list.stream().distinct().collect(Collectors.toList());
System.out.println(list2);
輸出:
[Product{name='product1', price='11.2'}, Product{name='product2', price='22.3'}, Product{name='product3', price='33.4'}]
1234567891011
元素Product需要重寫hashCode()
和equals()
方法。
sorted
sorted
方法是遍歷整個流的所有數據,并且在產生任何數據元素之前對它進行排序。需要實現 Comparable接口 和 Comparator接口。
List<Integer> list = new ArrayList<Integer>();
list.add(10);
list.add(39);
list.add(10);
list.add(78);
List<Integer> result =list.stream().sorted(Integer::compareTo).collect(Collectors.toList());
System.out.println(result);
輸出:
[10, 10, 39, 78]
123456789101112
聚合操作
見下章《Stream流 - 聚合操作和遍歷操作》
參考文章:
《Java學習筆記——Stream流》
原文鏈接:https://blog.csdn.net/qq_43985303/article/details/128968835
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2023-02-06 C語言預處理器使用方法講解_C 語言
- 2023-01-20 React?Redux管理庫示例詳解_React
- 2023-07-07 JdbcTemplate基本使用
- 2022-08-30 ORACLE分區表轉換在線重定義DBMS_REDEFINITION_oracle
- 2022-10-26 c語言數據結構之棧和隊列詳解(Stack&Queue)_C 語言
- 2022-10-17 docker?compose運行微服務項目的方法_docker
- 2022-07-11 go語言實現二叉樹的序例化與反序列化_Golang
- 2022-09-14 apache虛擬主機配置的三種方式(小結)_Linux
- 欄目分類
-
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支