Stream
流的生成
通过集合生成
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
Stream<Integer> stream = list .stream();
通过值生成
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
通过文件生成
Stream<String> lines = Files.lines(Paths.get("data.txt"), Charset.defaultCharset());
通过函数生成
- iterator
/**
* 该方法通过迭代器生成无限流,需要limit方法进行截断
* iterate: 内为迭代方法,即生成流的规则
* limit: 参数为生成的数量
*/
Stream<Integer> stream = Stream.iterate(0, n -> n + 2).limit(5);
- generator
/**
* 该方法通过迭代器生成无限流,需要limit方法进行截断
* generate: 内为生成器方法,即生成流的规则
* limit: 参数为生成的数量
*/
Stream<Double> stream = Stream.generate(Math::random).limit(5);
流的类型
Stream, IntStream, DoubleStream, LongStream,四种类型的流都继承自BaseStream,其中Stream代表引用类型的流,四者之间可以通过,mapToObj,mapToInt,mapToDouble,mapToLong进行转化。
操作类型
- 中间操作
一个流可以后面跟随零个或多个中间操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作都是惰性化的,仅仅调用到这类方法,并没有真正开始流的遍历,真正的遍历需等到终端操作时,常见的中间操作有下面即将介绍的 filter、map 等。
- 终端操作
一个流有且只能有一个终端操作,当这个操作执行后,流就被关闭了,无法再被操作,因此一个流只能被遍历一次,若想在遍历需要通过源数据在生成流。终端操作的执行,才会真正开始流的遍历。
方法
filter
- 筛选
- 参数为条件,返回所有该条件为true的元素
- 中间操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
Stream stream = list.stream().filter(i -> i > 3);
stream.forEach(System.out::println);
结果
4
5
6
Process finished with exit code 0
distinct
- 去重
- 中间操作
List<Integer> list = Arrays.asList(1, 1, 2, 3, 3, 4);
Stream stream = list.stream().distinct();
stream.forEach(System.out::println);
结果
1
2
3
4
sorted
- 排序
- 中间操作
List<String> list = Arrays.asList("java", "python", "go");
Stream stream;
//自然升序
stream = list.stream().sorted();
stream.forEach(System.out::println);
System.out.println("====================");
//自然降序
stream = list.stream().sorted(Comparator.reverseOrder());
stream.forEach(System.out::println);
System.out.println("====================");
//对象升序
stream = list.stream().sorted(Comparator.comparing(String::length));
stream.forEach(System.out::println);
System.out.println("====================");
//对象降序
stream = list.stream().sorted(Comparator.comparing(String::length).reversed());
stream.forEach(System.out::println);
System.out.println("====================");
//自定义排序规则
stream = list.stream().sorted(Comparator.comparing(s -> s.charAt(1)));
stream.forEach(System.out::println);
System.out.println("====================");
//多规则排序
stream = list.stream().sorted(Comparator.comparing(String::length).thenComparing(String::hashCode));
stream.forEach(System.out::println);
结果
go
java
python
====================
python
java
go
====================
go
java
python
====================
python
java
go
====================
java
go
python
====================
go
java
python
takeWhile
- 循环保留
- 保留第一个不满足条件的元素之前的所有元素,故如果将示例中条件改为i>4,则不会保留任何元素,返回为空
- 中间操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = list.stream().takeWhile(i -> (i < 4));
stream.forEach(System.out::println);
结果
1
2
3
dropWhile
- 循环舍弃
- 舍弃第一个不满足条件的元素之前的所有元素,故如果将示例中条件改为i>4,则不会舍弃任何元素,返回为从1到5
- 中间操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = list.stream().dropWhile(i -> (i < 4));
stream.forEach(System.out::println);
结果
4
5
peek
- 遍历
- peek为中间操作,forEach为终端操作,二者仅这点不同,peek常用来辅助调制
- 中间操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
list.stream()
.peek(System.out::println)
.dropWhile(i -> (i < 4))
.forEach(System.out::println);
结果
1
2
3
4
4
5
5
limit
- 前截取
- 参数为返回的元素个数
- 中间操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
Stream stream = list.stream().limit(3);
stream.forEach(System.out::println);
结果
1
2
3
skip
- 后截取
- 参数为跳过的元素个数
- 中间操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
Stream stream = list.stream().skip(2);
stream.forEach(System.out::println);
结果
3
4
5
6
map
- 映射
- 通过参数中的方法将元素映射为另个元素
- 中间操作
List<String> list = Arrays.asList("java", "python", "go");
Stream stream = list.stream().map(String::length);
stream.forEach(System.out::println);
结果
4
6
2
flatMap
- 扁平化流
- 将每一个值都转换成流,可以理解将多层结构转为单层的流
- 中间操作
/**
* 经过map之后的类型为 Stream<String[]>,可以认为是两层结构
* 经过flatMap后将map结果的流转换成扁平的单层流
*/
List<String> list = Arrays.asList("java 17", "python 3.9", "go 1.18");
Stream stream = list.stream()
.map(w -> w.split(" "))
.flatMap(Arrays::stream);
stream.forEach(System.out::println);
结果
java
17
python
3.9
go
1.18
allMatch
- 匹配所有元素
- 返回值为boolean,若参数对于所有元素均为true,则返回true,否则返回false;与noneMatch含义相反
- 中间操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
if (list.stream().allMatch(i -> i > 4)) {
System.out.println("所有元素值都大于4");
} else {
System.out.println("不是所有元素值都大于4");
}
结果
不是所有元素值都大于4
anyMatch
- 匹配其中一个元素
- 返回值为boolean,若参数对于任一元素为true,则返回true,否则返回false
- 中间操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
if (list.stream().anyMatch(i -> i > 4)) {
System.out.println("存在大于4的元素");
} else {
System.out.println("不存在大于4的元素");
}
结果
存在大于4的元素
noneMatch
- 所有元素不匹配
- 返回值为boolean,若参数对于所有元素均为false,则返回true,否则返回false;与allMatch含义相反
- 中间操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
if (list.stream().noneMatch(i -> i > 4)) {
System.out.println("不存在大于4的元素");
} else {
System.out.println("存在大于4的元素");
}
结果
存在大于4的元素
count
- 统计元素个数
- 返回流中的元素的个数,返回值为long型
- 终端操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
long count = list.stream().count();
System.out.println(count);
结果
5
findFirst
- 查找第一个
- 返回第一个元素,通常配合filter使用,返回满足过滤条件的第一个元素,返回类型为Optional
- 终端操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Optional result = list.stream().filter(i -> i > 3).findFirst();
System.out.println(result.orElse(-1));
结果
4
findAny
- 查找随机一个
- 返回随机一个元素,通常配合filter使用,返回满足过滤条件的随机一个元素,返回类型为Optional,在数据较少且串行的情况下,一般返回第一个,即与findFirst返回一致;若是数据较多或并行时,返回元素随机,findAny相比findFirst,更加高效
- 终端操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Optional result = list.stream().filter(i -> i > 3).findAny();
System.out.println(result.orElse(-1));
结果
4
reduce
- 裁减计算(其实不知道该怎么翻译好)
- 第一个参数是初始值,第二个参数为操作,相当于将初始值添加到流的头部,然后连续调用第二个参数的方法,对于累加、累乘的操作,更好理解
- 终端操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
int sum = list.stream()
.reduce(0, Integer::sum);
int product = list.stream()
.reduce(1, (a, b)->a * b);
System.out.println(sum);
System.out.println(product);
结果
15
120
max
- 最大值
- 返回最大的元素,参数为比较方法,通常为compare方法
- 终端操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> max = list.stream()
.max(Integer::compareTo);
System.out.println(max.orElse(-1));
结果
5
min
- 最小值
- 返回最小的元素,参数为比较方法,通常为compare方法
- 终端操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> min = list.stream()
.min(Integer::compareTo);
System.out.println(min.orElse(-1));
结果
1
foreach
- 遍历
- 终端操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
list.forEach(System.out::println);
结果
1
2
3
4
5
collect
- 返回集合
- 终端操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> intList = list.stream()
.collect(Collectors.toList());
通过Collectors.toXXX()方法,可以转换为其他集合类型,如:
toList: 转为List
toSet: 转为Set
toMap: 转为Map
joining
- 拼接
- 将元素通过参数拼接起来
- collect操作
List<String> list = Arrays.asList("java 17", "python 3.9", "go 1.18");
String str = list.stream()
.collect(Collectors.joining(";"));
System.out.println(str);
结果
java 17;python 3.9;go 1.18
groupingBy
- 分组
- 将元素按参数规则分组,分组方法可以嵌套,可以自定义
- collect操作
//单层分组
List<String> list = Arrays.asList("java", "python", "go", "delphi", "groovy", "perl");
Map<Integer, List<String>> map = list.stream()
.collect(Collectors.groupingBy(String::length));
System.out.println(map);
System.out.println("===================");
// //两层分组,二层为自定义条件
Map<Integer, Map<String, List<String>>> map2 = list.stream()
.collect(Collectors.groupingBy(String::length,
Collectors.groupingBy(s -> s.charAt(0) + "")));
System.out.println(map2);
结果
{2=[go], 4=[java, perl], 6=[python, delphi, groovy]}
===================
{2={g=[go]}, 4={p=[perl], j=[java]}, 6={p=[python], d=[delphi], g=[groovy]}}
partitioningBy
- 分组
- 参数返回为boolean型,根据布尔值分组,最多分两组
- collect操作
List<String> list = Arrays.asList("java", "python", "go", "delphi", "groovy", "perl");
Map<Boolean, List<String>> map = list.stream()
.collect(Collectors.partitioningBy(s -> s.length() > 4));
System.out.println(map);
结果
{false=[java, go, perl], true=[python, delphi, groovy]}