Stream(流)
# 什么是Stream
Java8添加了一个新的接口Stream(流),可以用函数式风格对数据进行处理。就像写sql语句一样。
流处理过程
+--------+ +--------+ +--------+
| 创建流 |+--->| 处理流 |+--->| 终止流 |
+--------+ +--------+ +--------+
1
2
3
2
3
流处理特点:
- 不保存数据
- 不修改数据
- 延迟处理,在获得结果的时候才会执行中间数据处理操作
流类型
- stream() − 创建串行流。
- parallelStream() − 创建并行流(内部使用Fork/Join线程模型处理)
# 创建流
流的数据源可以是:集合、数组、迭代器、生产器等
// list转stream
List<String> strList = new ArrayList<>();
Stream<String> listStream = strList.stream();
// 数组转stream
String[] strArr = new String[10];
Stream<String> arrStream = Arrays.stream(strArr);
// 通过静态方法创建流
Stream<String> stream = Stream.of("a", "b", "c");
// 通过种子创建无限流
Stream<Integer> iterStream = Stream.iterate(2, i -> i * i);
/*
* 2
* 4
* 8
* 16
* ...
*/
// 创建10个元素的流
Stream<Integer> iter10Stream = Stream.iterate(2, i -> i * 2).limit(3);
iter10Stream.forEach(System.out::println);
/*
* 2
* 4
* 8
*/
// 生产
Stream<Double> genStream = Stream.generate(Math::random).limit(3);
genStream.forEach(System.out::println);
/*
* 0.5875071685084056
* 0.622271393744705
* 0.7873169115032873
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 处理流
流的处理就像流水线一样,按照流程一步步处理下去
# 筛选与切片
- filter(Predicate p) - 过滤掉不符合条件的数据
- distinct() - 数据去重(使用hashCode和equals判断是否是相同数据)
- limit(long maxSize) - 截断操作,当已经获得maxSize个数据后,将不再继续筛选数据
- skip(long n) - 跳过前n个数据,如果数据不足n个,则返回一个空流
# 映射 - 将数据映射成其他类型的数据
- map(Function<? super T, ? extends R> mapper) - 将数据映射成新的类型
- mapToInt(ToIntFunction<? super T> mapper) - 将数据映射成Integer类型
- mapToLong(ToLongFunction<? super T> mapper) - 将数据映射成Long类型
- flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) - 将数据映射另外一个流,并将每个数据映射的流合并成一个流
# 排序
- sorted() - 字典排序
- sorted(Comparator<? super T> comparator) - 自定义排序
# 终止流
从一系列中间操作获得最终数据
# 匹配
- allMatch(Predicate<? super T> predicate) - 是否所有元素匹配
- anyMatch(Predicate<? super T> predicate) - 是否有至少一个数据匹配
- noneMatch(Predicate<? super T> predicate) - 是否没有数据匹配
# 查找
- findFirst() - 返回第一个数据
- findAny() - 返回任一数据
# 统计
- count() - 返回数据总数
- max(Comparator<? super T> comparator) - 返回数据的最大值
- min(Comparator<? super T> comparator) - 返回数据的最小值
# 迭代
- forEach(Consumer<? super T> action) - 内部跌倒方式获取数据
# 聚合
- reduce(BinaryOperator< T> accumulator) - 将数据聚合后获得一个新值,返回值是Optional类型
- reduce(T identity, BinaryOperator< T> accumulator) - 通过起始值identity将数据聚合后获得获得一个新的值
# 收集
- collect(Collector<? super T, A, R> collector) - 通过Collector接口,将数据收集成一个非Stream类型的集合
提示
可以用Collectors静态方法来创建Collector对象
- toList: 将数据转成List
- toSet: 将数据转成Set
- toMap: 将数据转成Map
- averagingDouble: 求数据平均值
- groupingBy: 对数据进行分组
其他更多方法查看Collectors api
# 示例
public static void main(String[] args) {
List<String> strList = Arrays.asList("a", " ", "sas", "1", "39", "as234",
"nba", "cba", "32", "25", "ss ", " srr ", "10", "", " bqwe");
// 查找出全部数字,按照字典排序,并将结果收集到List<Integer>
List<Integer> intList = strList.stream()
.filter(str -> str.trim().length() > 0)
.filter(str -> isInteger(str))
.map(str -> Integer.parseInt(str))
.sorted()
.collect(Collectors.toList());
System.out.println(intList);
// 查找出所有数字中最大的值是多少
Optional<Integer> max = strList.stream()
.filter(str -> str.trim().length() > 0)
.filter(str -> isInteger(str))
.map(str -> Integer.parseInt(str)).max((a, b) -> a - b);
System.out.println("max: " + max.get());
// 查找出所有数字的总和
Optional<Integer> sum = strList.stream()
.filter(str -> str.trim().length() > 0)
.filter(str -> isInteger(str))
.map(str -> Integer.parseInt(str))
.reduce((a, b) -> a + b);
System.out.println("sum: " + sum.get());
// 查找出所有数字的个数
long count = strList.stream()
.filter(str -> str.trim().length() > 0)
.filter(str -> isInteger(str))
.map(str -> Integer.parseInt(str))
.count();
System.out.println("count: " + count);
// 查找出所有数字的平均值
Double ave = strList.stream()
.filter(str -> str.trim().length() > 0)
.filter(str -> isInteger(str))
.map(str -> Integer.parseInt(str))
.collect(Collectors.averagingInt(value -> value));
System.out.println("ave: " + ave);
// 去掉所有字符串两边空格,并获得所有以字母a开头的字符串
strList.stream()
.map(str -> str.trim())
.filter(str -> str.startsWith("a"))
.filter(str -> !isInteger(str))
.forEach(System.out::println);
}
public static boolean isInteger(String str) {
Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
return pattern.matcher(str).matches();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
Last Updated: 2024/04/23, 01:30:37