企業(yè)手機(jī)網(wǎng)站案例/百度精準(zhǔn)營銷獲客平臺(tái)
在前兩篇博客中,我介紹了構(gòu)建 Stream 流的多種方式,以及 Stream API 的中間操作,如果你還沒有閱讀,你可以點(diǎn)擊這里和這里查看。
Java基礎(chǔ) - Stream 流:構(gòu)建流的多種方式
Java基礎(chǔ) - Stream 流:Stream API的中間操作
在這篇博客中,我將探索 Stream API 的終端操作,它們可以讓你從 Stream 流中得到最終的結(jié)果,或者產(chǎn)生一些副作用。
Stream API 的終端操作是指那些會(huì)消耗 Stream 流,產(chǎn)生一個(gè)最終的結(jié)果或者一個(gè)副作用的操作,它們不能再鏈?zhǔn)降卣{(diào)用,而是結(jié)束一個(gè)操作管道。Stream API 提供了很多終端操作,可以分為以下幾類:
- 歸約:這類操作可以讓你將 Stream 流中的所有元素合并為一個(gè)值,例如
reduce
,sum
,max
,min
,count
等。 - 收集:這類操作可以讓你將 Stream 流中的所有元素收集到一個(gè)集合或者一個(gè)值中,例如
collect
,toList
,toSet
,toMap
,joining
等。 - 遍歷:這類操作可以讓你對(duì) Stream 流中的每個(gè)元素執(zhí)行一個(gè)消費(fèi)者(Consumer)操作,例如
forEach
,forEachOrdered
等。 - 匹配:這類操作可以讓你判斷 Stream 流中的元素是否滿足一個(gè)條件,例如
anyMatch
,allMatch
,noneMatch
等。 - 查找:這類操作可以讓你從 Stream 流中找到一個(gè)元素,例如
findAny
,findFirst
等。
下面,我將用一些示例來展示這些終端操作的用法和效果。
1. 歸約
1.1 reduce
reduce
操作可以讓你將 Stream 流中的所有元素按照一個(gè)二元操作(BinaryOperator)進(jìn)行歸約,返回一個(gè) Optional 對(duì)象,它可能包含一個(gè)值,也可能為空。你也可以指定一個(gè)初始值,作為歸約的起點(diǎn)。例如:
// 創(chuàng)建一個(gè) Stream 流對(duì)象
Stream<Integer> numberStream = Stream.of(1, 2, 3, 4, 5);// 使用 reduce 操作將所有元素相加,不指定初始值
Optional<Integer> sum1 = numberStream.reduce((a, b) -> a + b);// 輸出 Optional[15]
System.out.println(sum1);// 使用 reduce 操作將所有元素相加,指定初始值為 0
int sum2 = numberStream.reduce(0, (a, b) -> a + b);// 輸出 15
System.out.println(sum2);
1.2 sum
sum
操作可以讓你將 Stream 流中的所有元素相加,返回一個(gè)數(shù)值。你需要將 Stream 流轉(zhuǎn)換為數(shù)值流,例如 IntStream
, LongStream
, DoubleStream
等。例如:
// 創(chuàng)建一個(gè) Stream 流對(duì)象
Stream<Integer> numberStream = Stream.of(1, 2, 3, 4, 5);// 使用 sum 操作將所有元素相加,需要轉(zhuǎn)換為 IntStream
int sum = numberStream.mapToInt(Integer::intValue).sum();// 輸出 15
System.out.println(sum);
1.3 max
max
操作可以讓你從 Stream 流中找到最大的元素,返回一個(gè) Optional 對(duì)象,它可能包含一個(gè)值,也可能為空。你可以指定一個(gè)比較器(Comparator)來定義元素的大小。例如:
// 創(chuàng)建一個(gè) Stream 流對(duì)象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 max 操作找到最大的元素,按照自然順序比較
Optional<String> max1 = animalStream.max(String::compareTo);// 輸出 Optional[yellow]
System.out.println(max1);// 使用 max 操作找到最大的元素,按照長(zhǎng)度比較
Optional<String> max2 = animalStream.max((s1, s2) -> s1.length() - s2.length());// 輸出 Optional[elephant]
System.out.println(max2);
1.4 min
min
操作可以讓你從 Stream 流中找到最小的元素,返回一個(gè) Optional 對(duì)象,它可能包含一個(gè)值,也可能為空。你可以指定一個(gè)比較器(Comparator)來定義元素的大小。例如:
// 創(chuàng)建一個(gè) Stream 流對(duì)象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 min 操作找到最小的元素,按照自然順序比較
Optional<String> min1 = animalStream.min(String::compareTo);// 輸出 Optional[cat]
System.out.println(min1);// 使用 min 操作找到最小的元素,按照長(zhǎng)度比較
Optional<String> min2 = animalStream.min((s1, s2) -> s1.length() - s2.length());// 輸出 Optional[cat] 或者 Optional[dog] 或者 Optional[fox]
System.out.println(min2);
1.5 count
count
操作可以讓你計(jì)算 Stream 流中的元素個(gè)數(shù),返回一個(gè)長(zhǎng)整型。例如:
// 創(chuàng)建一個(gè) Stream 流對(duì)象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 count 操作計(jì)算元素個(gè)數(shù)
long count = animalStream.count();// 輸出 5
System.out.println(count);
2. 收集
2.1 collect
collect
操作可以讓你將 Stream 流中的所有元素收集到一個(gè)集合或者一個(gè)值中,返回一個(gè)收集結(jié)果。你需要指定一個(gè)收集器(Collector)來定義收集的規(guī)則。例如:
// 創(chuàng)建一個(gè) Stream 流對(duì)象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 collect 操作將所有元素收集到一個(gè)列表中,使用預(yù)定義的收集器
List<String> list = animalStream.collect(Collectors.toList());// 輸出 [cat, dog, elephant, fox, giraffe]
System.out.println(list);// 使用 collect 操作將所有元素收集到一個(gè)字符串中,使用自定義的收集器
String string = animalStream.collect(StringBuilder::new, StringBuilder::append, StringBuilder::append).toString();// 輸出 catdogelephantfoxgiraffe
System.out.println(string);
2.2 toList
toList
操作可以讓你將 Stream 流中的所有元素收集到一個(gè)列表中,返回一個(gè)列表。它是一個(gè)預(yù)定義的收集器,可以直接使用。例如:
// 創(chuàng)建一個(gè) Stream 流對(duì)象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 toList 操作將所有元素收集到一個(gè)列表中
List<String> list = animalStream.toList();// 輸出 [cat, dog, elephant, fox, giraffe]
System.out.println(list);
2.3 toSet
toSet
操作可以讓你將 Stream 流中的所有元素收集到一個(gè)集合中,返回一個(gè)集合。它是一個(gè)預(yù)定義的收集器,可以直接使用。它會(huì)去除重復(fù)的元素。例如:
// 創(chuàng)建一個(gè) Stream 流對(duì)象
Stream<String> animalStream = Stream.of("cat", "dog", "cat", "elephant", "dog", "fox");// 使用 toSet 操作將所有元素收集到一個(gè)集合中
Set<String> set = animalStream.toSet();// 輸出 [cat, dog, elephant, fox]
System.out.println(set);
2.4 toMap
toMap
操作可以讓你將 Stream 流中的所有元素收集到一個(gè)映射中,返回一個(gè)映射。它是一個(gè)預(yù)定義的收集器,可以直接使用。你需要指定一個(gè)鍵函數(shù)(Key Function)和一個(gè)值函數(shù)(Value Function)來定義映射的鍵和值。你也可以指定一個(gè)合并函數(shù)(Merge Function)來處理重復(fù)的鍵。例如:
// 創(chuàng)建一個(gè) Stream 流對(duì)象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 toMap 操作將所有元素收集到一個(gè)映射中,以元素的首字母為鍵,以元素的長(zhǎng)度為值
Map<String, Integer> map1 = animalStream.collect(Collectors.toMap(s -> s.substring(0, 1), String::length));// 輸出 {c=3, d=3, e=8, f=3, g=7}
System.out.println(map1);// 使用 toMap 操作將所有元素收集到一個(gè)映射中,以元素的長(zhǎng)度為鍵,以元素為值,如果有重復(fù)的鍵,就用逗號(hào)連接值
Map<Integer, String> map2 = animalStream.collect(Collectors.toMap(String::length, s -> s, (s1, s2) -> s1 + ", " + s2));// 輸出 {3=cat, dog, fox, 8=elephant, 7=giraffe}
System.out.println(map2);
2.5 joining
joining
操作可以讓你將 Stream 流中的所有元素連接成一個(gè)字符串,返回一個(gè)字符串。它是一個(gè)預(yù)定義的收集器,可以直接使用。你可以指定一個(gè)分隔符(Delimiter)來分隔元素,也可以指定一個(gè)前綴(Prefix)和一個(gè)后綴(Suffix)來包裹字符串。例如:
// 創(chuàng)建一個(gè) Stream 流對(duì)象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 joining 操作將所有元素連接成一個(gè)字符串,不指定分隔符,前綴和后綴
String string1 = animalStream.collect(Collectors.joining());// 輸出 catdogelephantfoxgiraffe
System.out.println(string1);// 使用 joining 操作將所有元素連接成一個(gè)字符串,指定分隔符為逗號(hào),前綴為左括號(hào),后綴為右括號(hào)
String string2 = animalStream.collect(Collectors.joining(", ", "(", ")"));// 輸出 (cat, dog, elephant, fox, giraffe)
System.out.println(string2);
3. 遍歷
3.1 forEach
forEach
操作可以讓你對(duì) Stream 流中的每個(gè)元素執(zhí)行一個(gè)消費(fèi)者(Consumer)操作,不返回任何結(jié)果。它是一個(gè)終端操作,會(huì)消耗 Stream 流。它不保證按照數(shù)據(jù)源的順序執(zhí)行,如果需要保證順序,可以使用 forEachOrdered
操作。例如:
// 創(chuàng)建一個(gè) Stream 流對(duì)象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 forEach 操作對(duì)每個(gè)元素打印一個(gè)消息
animalStream.forEach(s -> System.out.println("I like " + s));// 可能輸出 I like fox, I like dog, I like cat, I like elephant, I like giraffe
3.2 forEachOrdered
forEachOrdered
操作可以讓你對(duì) Stream 流中的每個(gè)元素按照數(shù)據(jù)源的順序執(zhí)行一個(gè)消費(fèi)者(Consumer)操作,不返回任何結(jié)果。它是一個(gè)終端操作,會(huì)消耗 Stream 流。它保證按照數(shù)據(jù)源的順序執(zhí)行,但可能會(huì)影響并行性能。例如:
// 創(chuàng)建一個(gè) Stream 流對(duì)象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 forEachOrdered 操作對(duì)每個(gè)元素按照數(shù)據(jù)源的順序打印一個(gè)消息
animalStream.forEachOrdered(s -> System.out.println("I like " + s));// 輸出 I like cat, I like dog, I like elephant, I like fox, I like giraffe
4. 匹配
4.1 anyMatch
anyMatch
操作可以讓你判斷 Stream 流中是否有任意一個(gè)元素滿足一個(gè)謂詞(Predicate),返回一個(gè)布爾值。它是一個(gè)短路的終端操作,只要找到一個(gè)滿足條件的元素就會(huì)停止。例如:
// 創(chuàng)建一個(gè) Stream 流對(duì)象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 anyMatch 操作判斷是否有以 f 開頭的元素
boolean hasF = animalStream.anyMatch(s -> s.startsWith("f"));// 輸出 true
System.out.println(hasF);
4.2 allMatch
allMatch
操作可以讓你判斷 Stream 流中是否所有的元素都滿足一個(gè)謂詞(Predicate),返回一個(gè)布爾值。它是一個(gè)短路的終端操作,只要找到一個(gè)不滿足條件的元素就會(huì)停止。例如:
// 創(chuàng)建一個(gè) Stream 流對(duì)象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 allMatch 操作判斷是否所有的元素都包含 a
boolean allA = animalStream.allMatch(s -> s.contains("a"));// 輸出 false
System.out.println(allA);
4.3 noneMatch
noneMatch
操作可以讓你判斷 Stream 流中是否沒有任何一個(gè)元素滿足一個(gè)謂詞(Predicate),返回一個(gè)布爾值。它是一個(gè)短路的終端操作,只要找到一個(gè)滿足條件的元素就會(huì)停止。例如:
// 創(chuàng)建一個(gè) Stream 流對(duì)象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 noneMatch 操作判斷是否沒有以 z 結(jié)尾的元素
boolean noZ = animalStream.noneMatch(s -> s.endsWith("z"));// 輸出 true
System.out.println(noZ);
5. 查找
5.1 findAny
findAny
操作可以讓你從 Stream 流中找到任意一個(gè)元素,返回一個(gè) Optional 對(duì)象,它可能包含一個(gè)值,也可能為空。它是一個(gè)短路的終端操作,只要找到一個(gè)元素就會(huì)停止。它不保證返回第一個(gè)元素,如果需要保證順序,可以使用 findFirst
操作。例如:
// 創(chuàng)建一個(gè) Stream 流對(duì)象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 findAny 操作找到任意一個(gè)元素
Optional<String> anyAnimal = animalStream.findAny();// 輸出 Optional[cat] 或者其他值
System.out.println(anyAnimal);
5.2 findFirst
findFirst
操作可以讓你從 Stream 流中找到第一個(gè)元素,返回一個(gè) Optional 對(duì)象,它可能包含一個(gè)值,也可能為空。它是一個(gè)短路的終端操作,只要找到第一個(gè)元素就會(huì)停止。它保證返回第一個(gè)元素,但可能會(huì)影響并行性能。例如:
// 創(chuàng)建一個(gè) Stream 流對(duì)象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 findFirst 操作找到第一個(gè)元素
Optional<String> firstAnimal = animalStream.findFirst();// 輸出 Optional[cat]
System.out.println(firstAnimal);
?