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