stream流添加终端操作
避免使用reduce()
归约操作
使用reduce()
并不是最简单的归约方法。
You need to make sure that the binary operator you provide is associative, then you need to know if it has an identity element.
计算stream流中的元素个数
示例
Collection<String> strings =
List.of("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten");
long count =
strings.stream()
.filter(s -> s.length() == 3)
.count();
System.out.println("count = " + count);
结果
count = 4
依次消费stream流中的元素
foreach()
示例1
Stream<String> strings = Stream.of("one", "two", "three", "four");
strings.filter(s -> s.length() == 3)
.map(String::toUpperCase)
.forEach(System.out::println);
结果
ONE
TWO
示例2
Stream<String> strings = Stream.of("one", "two", "three", "four");
List<String> result = new ArrayList<>();
strings.filter(s -> s.length() == 3)
.map(String::toUpperCase)
.forEach(result::add);
System.out.println("result = " + result);
结果
result = [ONE, TWO]
示例2的改写
Stream<String> strings = Stream.of("one", "two", "three", "four");
List<String> result =
strings.filter(s -> s.length() == 3)
.map(String::toUpperCase)
.collect(Collectors.toList());
jdk16可以改写成
Stream<String> strings = Stream.of("one", "two", "three", "four");
List<String> result =
strings.filter(s -> s.length() == 3)
.map(String::toUpperCase)
.toList();
注意返回的result
是不可变的。
在集合或数组中收集stream流元素
Stream API提供了几种收集stream流中被处理的数据到集合中。
在你选择你所需的模式前你需要考虑以下的问题:
-
你是否需要构建一个不变的
List
-
你是需要
ArrayList
还是LinkedList
-
你是否确切的知道所处理的stream流的具体元素个数
-
你是否需要收集到第三方或者自己定义的
List
收集到ArrayList
示例
Stream<String> strings = Stream.of("one", "two", "three", "four");
List<String> result =
strings.filter(s -> s.length() == 3)
.map(String::toUpperCase)
.collect(Collectors.toList());
这是最简单的方法,但请注意当stream流中元素很多,会造成ArrayList
拷贝到更大ArrayList
并伴随着gc收集之前ArrayList
。
可以使用Collectors.toCollection()
指定更大容量大ArrayList
避免多次gc
Stream<String> strings = ...;
List<String> result =
strings.filter(s -> s.length() == 3)
.map(String::toUpperCase)
.collect(Collectors.toCollection(() -> new ArrayList<>(10_000)));
收集到不变的List
示例
Stream<String> strings = ...;
List<String> result =
strings.filter(s -> s.length() == 3)
.map(String::toUpperCase)
.collect(Collectors.toUnmodifiableList()));
jdk16
Stream<String> strings = ...;
List<String> result =
strings.filter(s -> s.length() == 3)
.map(String::toUpperCase)
.toList();
收集到自制的List
使用Collectors.toCollection()
Stream<String> strings = ...;
List<String> result =
strings.filter(s -> s.length() == 3)
.map(String::toUpperCase)
.collect(Collectors.toCollection(LinkedList::new));
收集到Set
可以使用Collectors.toCollection(HashSet::new)
或者更简洁的Collectors.toSet()
,注意这俩者还是有细微的差别,后面介绍。
Stream<String> strings = ...;
Set<String> result =
strings.filter(s -> s.length() == 3)
.map(String::toUpperCase)
.collect(Collectors.toSet());
如果你需要收集到不变的Set
Stream<String> strings = ...;
Set<String> result =
strings.filter(s -> s.length() == 3)
.map(String::toUpperCase)
.collect(Collectors.toUnmodifiableSet());
收集到数组
示例
Stream<String> strings = ...;
String[] result =
strings.filter(s -> s.length() == 3)
.map(String::toUpperCase)
.toArray(String[]::new);
System.out.println("result = " + Arrays.toString(result));
结果
result = [ONE, TWO]
提取stream流中最大和最小元素
示例
Stream<String> strings = Stream.of("one", "two", "three", "four");
String longest =
strings.max(Comparator.comparing(String::length))
.orElseThrow();
System.out.println("longest = " + longest);
结果
longest = three
stream流中查找元素
findFirst()
, findAny()
Collection<String> strings =
List.of("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten");
String first =
strings.stream()
// .unordered()
// .parallel()
.filter(s -> s.length() == 3)
.findFirst()
.orElseThrow();
System.out.println("first = " + first);
结果
first = one
检查stream流中的元素是否与给定的Predicate
匹配
-
anyMatch(predicate)
只要stream流中有一个元素匹配就返回true
-
allMatch(predicate)
stream流中所有元素都匹配才返回true
-
noneMatch(predicate)
stream流中没有一个元素匹配才返回true
Collection<String> strings =
List.of("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten");
boolean noBlank =
strings.stream()
.allMatch(Predicate.not(String::isBlank));
boolean oneGT3 =
strings.stream()
.anyMatch(s -> s.length() == 3);
boolean allLT10 =
strings.stream()
.noneMatch(s -> s.length() > 10);
System.out.println("noBlank = " + noBlank);
System.out.println("oneGT3 = " + oneGT3);
System.out.println("allLT10 = " + allLT10);
结果
noBlank = true
oneGT3 = true
allLT10 = true
stream流的短路处理
stream流的终端处理分类:一些需要处理完所有的元素才返回,例如count()
, max()
, min()
, average()
, forEach()
, toList()
, toArray()
等。一些不需要处理完所有数据即可返回,例如findFirst()
, findAny()
, anyMatch()
, allMatch()
, noneMatch()
。
短路处理:无需处理stream流的所有元素即可产生结果。