一、概述
Stream 流是 Java 8 新提供给开发者的一组操作集合的 API,将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选、排序、聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由终端操作 (terminal operation) 得到前面处理的结果。Stream 流可以极大的提高开发效率,也可以使用它写出更加简洁明了的代码。
stream流特点
- 不是数据结构,不会保存数据,只是在原数据集上定义了一组操作
- 惰性求值,流在中间处理过程中,只是对操作进行了记录,并不会立即执行,需要等到执行终止操作的时候才会进行实际的计算
- Stream不保存数据,它会将操作后的数据保存到另外一个对象中
Stream可以由数组或集合创建,对流的操作分为两种:
中间操作,每次返回一个新的流,可以有多个。(筛选filter、映射map、排序sorted、去重组合skip—limit)
终端操作,每个流只能进行一次终端操作,终端操作结束后流无法再次使用。终端操作会产生一个新的集合或值。(遍历foreach、匹配find–match、规约reduce、聚合max–min–count、收集collect)
stream和parallelStream的简单区分
stream是顺序流,由主线程按顺序对流执行操作,而parallelStream是并行流,内部以多线程并行执行的方式对流进行操作,但前提是流中的数据处理没有顺序要求。如果流中的数据量足够大,并行流可以加快处速度。除了直接创建并行流,还可以通过parallel()把顺序流转换成并行流:
1
| Optional<Integer> findFirst = list.stream().parallel().filter(x->x>6).findFirst();
|
二、stream流的常用方法
Stream流的常用方法:
终结方法:返回值类型不再是Stream接口本身类型的方法,例如:forEach方法和count方法
非终结方法/延迟方法:返回值类型仍然是Stream接口自身类型的方法,除了终结方法都是延迟方法。例如:filter,limit,skip,map,conat
方法名称 |
方法作用 |
方法种类 |
是否支持链式调用 |
count |
统计个数 |
终结方法 |
否 |
forEach |
逐一处理 |
终结方法 |
否 |
filter |
过滤 |
函数拼接 |
是 |
limit |
取用前几个 |
函数拼接 |
是 |
skip |
跳过前几个 |
函数拼接 |
是 |
map |
映射 |
函数拼接 |
是 |
concat |
组合 |
函数拼接 |
是 |
示例
count方法
long count (); 统计流中的元素,返回long类型数据
1 2 3 4 5 6 7 8 9 10 11
| List<String> list = new ArrayList<>(); list.add("张老三"); list.add("张小三"); list.add("李四"); list.add("赵五"); list.add("张六"); list.add("王八"); long count = list.stream().count(); System.out.println("集合中的元素个数是:" + count);
|
filter方法
Stream filter(Predicate super ?> predicate); 过滤出满足条件的元素
参数Predicate:函数式接口,抽象方法:boolean test (T t)
Predicate接口:是一个判断接口
1 2 3 4 5 6 7 8
| Stream<String> stream = Stream.of("张老三", "张小三", "李四", "赵五", "刘六", "王七");
stream.filter((String name)->{ return name.startsWith("张"); }).forEach((String name)->{ System.out.println("流中的元素" + name); });
|
forEach方法
void forEach(Consumer<? super T> action):逐一处理流中的元素
参数 Consumer<? super T> action:函数式接口,只有一个抽象方法:void accept(T t);
注意:
1.此方法并不保证元素的逐一消费动作在流中是有序进行的(元素可能丢失)
2.Consumer是一个消费接口(可以获取流中的元素进行遍历操作,输出出去),可以使用Lambda表达式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| List<String> list = new ArrayList<>(); list.add("张老三"); list.add("张小三"); list.add("李四"); list.add("赵五"); list.add("张六"); list.add("王八");
list.stream().forEach((String name)->{ System.out.println(name); }); 输出结果: 张老三 张小三 李四 赵五 张六 王八
|
limit方法
Stream limit(long maxSize); 取用前几个元素
注意:参数是一个long 类型,如果流的长度大于参数,则进行截取;否则不进行操作
1 2 3 4 5 6 7 8 9 10 11
| Stream<String> stream1 = Stream.of("张老三", "张小三", "李四", "赵五", "刘六", "王七");
stream1.limit(3).forEach((String name)->{ System.out.println("流中的前三个元素是:" + name); }); 输出结果: 流中的前三个元素是:张老三 流中的前三个元素是:张小三 流中的前三个元素是:李四
|
map方法
Stream map(Function<? super T,? exception R> mapper;
参数Function<T,R>:函数式接口,抽象方法:R apply(T t);
Function<T,R>:其实就是一个类型转换接口(T和R的类型可以一致,也可以不一致)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| Stream<String> stream1 = Stream.of("11","22","33","44","55");
stream1.map((String s)->{ return Integer.parseInt(s); }).forEach((Integer i)->{ System.out.println(i); }); 输出结果: 11 22 33 44
|
skip方法
Stream skip(long n); 跳过前几个元素
注意:如果流的当前长度大于n,则跳过前n个,否则将会得到一个长度为0的空流
1 2 3 4 5 6 7 8 9 10 11
| Stream<String> stream = Stream.of("张老三", "张小三", "李四", "赵五", "刘六", "王七"); stream.skip(3).forEach((String name)->{ System.out.println("跳过前三个,打印剩下的" + name); }); 输出结果: 跳过前三个,打印剩下的赵五 跳过前三个,打印剩下的刘六 跳过前三个,打印剩下的王七
|
concat方法
public static Stream concat(Stream<? extends T> a, Stream<? extends T> b) –> 合并两个流
1 2 3 4 5 6 7 8 9 10 11
| Stream<String> stream1 = Stream.of("11","22","33","44","55"); Stream<String> stream2 = Stream.of("张颜宇", "张三", "李四", "赵五", "刘六", "王七");
Stream<String> stream = Stream.concat(stream1,stream2); stream.forEach((String name)->{ System.out.print(name); }); 输出结果: 1122334455张颜宇张三李四赵五刘六王七
|
distinct方法
sorted方法
anyMatch方法
allMatch方法
noneMatch方法
findFirst和findAny方法
max和min方法
reduce方法
三、收集Stream流
Stream流中提供了一个方法,可以把流中的数据收集到单例集合中
<R, A> R collect(Collector<? super T, A, R> collector); 把流中的数据手机到单列集合中
返回值类型是R。R指定为什么类型,就是手机到什么类型的集合
参数Collector<? super T, A, R>中的R类型,决定把流中的元素收集到哪个集合中
参数Collector如何得到 ?,可以使用 java.util.stream.Collectors工具类中的静态方法:
- public static Collector<T, ?, List> toList():转换为List集合
- public static Collector<T, ?, Set> toSet() :转换为Set集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| List<String> list2 = new ArrayList<>(); list2.add("张老三"); list2.add("张小三"); list2.add("李四"); list2.add("赵五"); list2.add("张六"); list2.add("王八");
Stream<String> stream = list2.stream().filter((String name) -> { return name.startsWith("张"); }).filter((String name) -> { return name.length() == 3; });
List<String> list = stream.collect(Collectors.toList()); System.out.println(list);
Set<String> set = stream.collect(Collectors.toSet()); System.out.println(set);
|