Java Stream流與使用操作指南
一、什么是stream流
Java 8引入的Stream API是處理集合數(shù)據(jù)的一種全新方式,它代表了對數(shù)據(jù)元素序列進行函數(shù)式操作的抽象。Stream不是數(shù)據(jù)結(jié)構(gòu),而是一種高級的數(shù)據(jù)處理工具,允許你以聲明式的方式處理數(shù)據(jù)集合,類似于SQL語句操作數(shù)據(jù)庫。
Stream的核心特點:
- 聲明式編程:只需說明"做什么"而非"如何做",代碼更簡潔易讀
- 函數(shù)式風(fēng)格:與Lambda表達式完美結(jié)合,操作更靈活
- 管道操作:多個操作可以連接起來形成數(shù)據(jù)處理流水線
- 內(nèi)部迭代:不同于集合的外部迭代(使用for-each),Stream在內(nèi)部處理迭代過程
- 延遲執(zhí)行:中間操作不會立即執(zhí)行,只有遇到終結(jié)操作才會觸發(fā)計算
- 不可復(fù)用:一個Stream只能被消費一次
二、創(chuàng)建stream流
1.單列集合創(chuàng)建stream流
// 1.單列集合創(chuàng)建stream流
List<String> list = Arrays.asList("張三", "李四", "王五", "趙六", "錢七");
list.stream().forEach(e -> System.out.println("e = " + e));2.雙列集合創(chuàng)建stream流
// 2.雙列集合創(chuàng)建stream流
HashMap<String, Integer> map = new HashMap<>();
map.put("aaa", 111);
map.put("bbb", 222);
map.put("ccc", 333);
map.put("ddd", 444);
map.put("eee", 555);
// 遍歷所有的key
map.keySet().stream().forEach(e -> System.out.println("e = " + e));
// 遍歷所有的鍵值對
map.entrySet().stream().forEach(e -> System.out.println("e = " + e));
// 遍歷所有的值
map.values().stream().forEach(e -> System.out.println("e = " + e));3.數(shù)組創(chuàng)建stream流
// 3.數(shù)組創(chuàng)建stream流
int[] array1 = {1, 2, 3};
String[] array2 = {"a", "b", "c"};
Arrays.stream(array1).forEach(e -> System.out.println("e = " + e));4.零散數(shù)據(jù)創(chuàng)建stream流
// 4.零散數(shù)據(jù)創(chuàng)建stream流
Stream.of(1, 2, 3, 4, 5).forEach(e -> System.out.println("e = " + e));
// stream接口中靜態(tài)方法of的細節(jié)
// 方法的形參是一個可變參數(shù),可以傳遞一堆零散的數(shù)據(jù)(同一類型),也可以傳遞數(shù)組
// 傳遞的數(shù)組必須是引用數(shù)據(jù)類型的,如果傳遞基本數(shù)據(jù)類型,會把數(shù)組當做一個元素
Stream.of(array1).forEach(e -> System.out.println("e = " + e)); // 結(jié)果[I@4dd8dc3
Stream.of(array2).forEach(e -> System.out.println("e = " + e));5.創(chuàng)建并行流
// 5.創(chuàng)建并行流
list.parallelStream().forEach(e -> System.out.println("e = " + e)); // 順序會打亂6.創(chuàng)建無限流
// 6.創(chuàng)建無限流
Stream.generate(Math::random).limit(10).forEach(e -> System.out.println("e = " + e));
Stream.iterate(0, n -> n + 2).limit(10).forEach(e -> System.out.println("e = " + e));三、流的中間操作
中間操作返回一個新的Stream,可以鏈式調(diào)用多個中間操作。
注意點:
一、中間方法,返回新的stream流,原來的stream流只能使用一次,建議使用鏈式編程
二、修改stream流中的數(shù)據(jù),不會影響原來集合或數(shù)組中的數(shù)據(jù)
1.過濾操作
// 1.過濾操作
// filter: 過濾元素
List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 100, 100);
List<Integer> list2 = Arrays.asList(100, 200, 30, 40, 50, 60, 70, 80, 90, 100, 200, 1000, 100000);
list1.stream().filter(n -> n % 2 == 0).forEach(e -> System.out.println("e = " + e));
// distinct: 去重
// 依賴于hashCode和equals方法,底層使用的是hashset
list1.stream().distinct().forEach(e -> System.out.println("e = " + e));2.映射操作
// 2.映射操作
List<String> list3 = Arrays.asList("張三-13", "李四-14", "王五-15", "趙六-16", "錢七-17");
list3.stream().map(s -> Integer.valueOf(s.split("-")[1])).forEach(e -> System.out.println("map = " + e));
List<List<Integer>> numberLists = Arrays.asList(
Arrays.asList(1, 2),
Arrays.asList(3, 4, 5),
Arrays.asList(6)
);
// flatMap 可以處理嵌套集合或需要"展平"數(shù)據(jù)結(jié)構(gòu)的情況,將每個元素轉(zhuǎn)換為一個流(Stream),然后把所有流合并成一個流
// 當你需要處理嵌套結(jié)構(gòu)或一對多轉(zhuǎn)換時,使用flatMap;當只是簡單的一對一轉(zhuǎn)換時,使用map
numberLists.stream().map(s -> s.stream()).forEach(stream -> System.out.println("stream = " + stream)); // 輸出3個流對象的地址值 java.util.stream.ReferencePipeline$Head@3b9a45b3
numberLists.stream().flatMap(s -> s.stream()).forEach(s -> System.out.println("flatMap = " + s)); // 輸出 1 2 3 4 5 63.截取/跳過操作
// 3.截取/跳過操作
// limit: 限制元素數(shù)量
list1.stream().limit(4).forEach(e -> System.out.println("e = " + e));
// skip: 跳過前N個元素
list1.stream().skip(5).forEach(e -> System.out.println("e = " + e));4.排序操作
// 4.排序操作
// sorted: 排序
Stream.of("b", "a", "c").sorted().forEach(s -> System.out.println("sorted = " + s));
// 自定義排序
Stream.of("aaa", "bb", "c").sorted(Comparator.comparingInt(String::length)).forEach(s -> System.out.println("customSorted = " + s));
Stream.of("aaa", "bb", "c", null).sorted((a, b) -> {
if (a == null && b == null) return 0;
if (a == null) return 1;
if (b == null) return -1;
return b.compareTo(a);
}).forEach(s -> System.out.println("customSorted2 = " + s));5.合并操作 ??????
// 5.合并操作
Stream.concat(list1.stream(), list2.stream()).forEach(e -> System.out.println("e = " + e));6.其他中間操作
此API可以很好的證明流“延遲執(zhí)行”的特點,當無forEach()時,不會打印出中間元素,當有終結(jié)操作時,流才會執(zhí)行。 ??????
// 6.其他中間操作
// peek: 查看流中元素,調(diào)試用
Stream.of("one", "two", "three")
.peek(e -> System.out.println("Original: " + e))
.map(String::toUpperCase)
.peek(e -> System.out.println("Mapped: " + e))
.forEach(e-> System.out.println("peek = " + e));四、 流的終結(jié)操作
終結(jié)操作會觸發(fā)流的處理并返回結(jié)果
1.遍歷操作 ??????
// 1.遍歷操作
List<String> list = Arrays.asList("張三-13", "李四-14", "王五-15", "趙六-16", "錢七-17", "張三-23");
// forEach: 遍歷元素
list.stream().forEach(e -> System.out.println("e = " + e));
// forEachOrdered: 保證順序的遍歷
list.parallelStream().forEachOrdered(e -> System.out.println("e = " + e));2.收集操作 ??????
// 2.收集操作
// 收集到list集合
List<String> nameList = list.stream().map(e -> e.split("-")[0]).collect(Collectors.toList());
System.out.println("nameList = " + nameList);
// 收集到set集合,會去重
Set<String> nameSet = list.stream().map(e -> e.split("-")[0]).collect(Collectors.toSet());
System.out.println("nameSet = " + nameSet);
// 收集到map集合
// 注意收集到map,鍵不能重復(fù),重復(fù)會報 java.lang.IllegalStateException: Duplicate key 張三 (attempted merging values 13 and 23)
// Map<String, Integer> map1 = list.stream().collect(Collectors.toMap(s -> s.split("-")[0], s -> Integer.valueOf(s.split("-")[1])));
// System.out.println("map1 = " + map1);
// 解決方案,傳遞第三個參數(shù),如果鍵重復(fù),使用前面的那么,以下的(a, b)代表的value,a為已經(jīng)存在的,b為新加的
Map<String, Integer> map2 = list.stream().collect(Collectors.toMap(s -> s.split("-")[0], s -> Integer.valueOf(s.split("-")[1]), (a, b) -> a));
System.out.println("map2 = " + map2);
// 收集為字符串
String nameStr = list.stream().map(e -> e.split("-")[0]).collect(Collectors.joining("-"));
System.out.println("nameStr = " + nameStr); // 張三-李四-王五-趙六-錢七-張三3.聚合操作
// 3.聚合操作
// count: 計數(shù)
long count = Stream.of("a", "b", "c").count();
System.out.println("count = " + count); // 3
// max/min: 最大最小值
Optional<String> max = Stream.of("a", "bb", "ccc").max(Comparator.comparingInt(String::length));
System.out.println("max = " + max.get());
// reduce: 歸約操作
// 無初始值,當流為空,則為Optional.empty()
Optional<Integer> sum = Stream.of(1, 2, 3).reduce(Integer::sum);
System.out.println("sum = " + sum.get()); // ccc
// 初始值為0,流為空則返回0,執(zhí)行的操作為 0+1+2+3 = 6
Integer sumWithIdentity = Stream.of(1, 2, 3).reduce(0, Integer::sum);
System.out.println("sumWithIdentity = " + sumWithIdentity); // 64.匹配操作 ?????
// 4.匹配操作
// anyMatch: 任意元素匹配(任意一個滿足條件則為true)
boolean hasEven = Stream.of(1, 2, 3).anyMatch(n -> n % 2 == 0);
System.out.println("hasEven = " + hasEven); // true
// allMatch: 所有元素匹配(所有元素都要滿足條件)
boolean allEven = Stream.of(2, 4, 6).allMatch(n -> n % 2 == 0);
System.out.println("allEven = " + allEven); // true
// noneMatch: 沒有元素匹配(所有元素都不能滿足條件)
boolean noneNegative = Stream.of(1, 2, 3).noneMatch(n -> n < 0);
System.out.println("noneNegative = " + noneNegative); // true5.查找操作 ??????
// 5.查找操作
// findFirst: 查找第一個元素
Optional<String> first = Stream.of("a", "b", "c").findFirst();
System.out.println("first = " + first.get()); // a
// findAny: 查找任意元素(在并行流中效率更高)
Optional<String> any = Stream.of("a", "b", "c").parallel().findAny();
System.out.println("any = " + any.get()); // b6.數(shù)組轉(zhuǎn)換
// 6.數(shù)組轉(zhuǎn)換
// toArray: 轉(zhuǎn)換為數(shù)組
String[] array = Stream.of("a", "b", "c").toArray(String[]::new);
System.out.println("array = " + Arrays.toString(array)); // [a, b, c]7.分組
// 7.分組
// 可將一個對象集合按照里面的某個字段轉(zhuǎn)換為map,如key為ID,value為對象
List<String> words = Arrays.asList("apple", "banana", "orange", "pear", "grape");
Map<Integer, List<String>> groupedByLength = words.stream()
.collect(Collectors.groupingBy(String::length));
System.out.println(groupedByLength);到此這篇關(guān)于Java Stream流與使用操作指南的文章就介紹到這了,更多相關(guān)Java Stream流內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Swagger2不被SpringSecurity框架攔截的配置及說明
這篇文章主要介紹了Swagger2不被SpringSecurity框架攔截的配置及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03
Java Web使用簡單的批處理操作(記事本+Tomcat)
這篇文章主要介紹了Java Web使用簡單的批處理操作 ,需要的朋友可以參考下2014-10-10
JVM(Java虛擬機)簡介(動力節(jié)點Java學(xué)院整理)
Java虛擬機(Jvm)是可運行Java代碼的假想計算機。Java虛擬機包括一套字節(jié)碼指令集、一組寄存器、一個棧、一個垃圾回收堆和一個存儲方法域。對java jvm 虛擬機感興趣的朋友通過本文一起學(xué)習(xí)吧2017-04-04

