原文链接:https://blog.csdn.net/bluuusea/article/details/79967039

Stream类全路径为:java.util.stream.Stream
对Stream的描述,引用其他文章中觉得比较好的介绍:

Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。
即Stream的原理:

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
集合有两种方式生成流:
- stream() − 为集合创建串行流。
- parallelStream() − 为集合创建并行流。

并发模式(parallelStream)能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。java中也提供了多种并行处理的方式,看到一片文章对各几种并行的方式性能进行了测试,可以参考下:java中几种并行方式的性能分析。

Stream的的中间操作(intermediate)和最终操作(terminal)都包含哪些方法可以从类结构中看到:

上面截图基本包含了Strram的所有方法。

中间操作(intermediate)主要有以下方法(此类型的方法返回的都是Stream对象):
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered

终端操作(terminal)主要有以下方法:
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

此处按照类结构(截图)中的方法的顺序(以下例子中使用了Lambda表达式及方法引用,不了解的请戳:Lambda介绍,方法引用),进行介绍:

filter:通过设置条件来过滤元素。
List<String> list = Arrays.asList("aaa","ddd","bbb","ccc","a2a","d2d","b2b","c2c","a3a","d3d","b3b","c3c");

list.stream()
.filter((s)->s.contains("a"))
.forEach(s -> System.out.println(s));
1
2
3
4
5
以上代码使用filter方法过滤出只包含”a”的元素,然后通过forEach将满足条件的元素遍历出来。输出如下:

aaa
a2a
a3a
map:就是将对应的元素使用给定方法进行转换。
list.stream()
.filter((s)->s.contains("a"))
.map((s)-> s + "---map")
.forEach(s -> System.out.println(s));
1
2
3
4
5
在filter的基础上,给每个元素后面添加字符串”—map”,输出如下:

aaa—map
a2a—map
a3a—map
mapToInt:和map方法进行一样的操作,但是转换函数必须返回int类型
mapToLong:和map方法进行一样的操作,但是转换函数必须返回long类型
mapToDouble:和map方法进行一样的操作,但是转换函数必须返回double类型
此处以mapToInt进行演示:
list.stream()
.filter((s)->s.contains("a"))
.mapToInt((s)-> s.hashCode())
.forEach(s -> System.out.println(s));
1
2
3
4
在filter的基础上,将每个元素转换为其hashCode。输出为:

96321
94864
94895
flatMap:如果流的元素为数组或者Collection,flatMap就是将每个Object[]元素或Collection<Object>元素都转换为Object元素,如下:
Stream<String[]> 转换为 Stream<String>
Stream<Set> 转换为 Stream<String>
Stream<List> 转换为 Stream<String>
Stream<List> 转换为 Stream<Object>
看下例子:

List<String[]> setList = new ArrayList<>();
setList.add(new String[]{"aa","bb"});
setList.add(new String[]{"cc","dd"});
setList.add(new String[]{"ee","ff"});
//使用map方法
setList.stream()
.map(s->Arrays.stream(s))
.forEach(s-> System.out.println("map==" + s));
//使用flatMap方法
setList.stream()
.flatMap(s->Arrays.stream(s))
.forEach(s-> System.out.println("flatMap==" + s));
1
2
3
4
5
6
7
8
9
10
11
12
输出如下:

map==java.util.stream.ReferencePipeline&Head@50040f0c
map==java.util.stream.ReferencePipeline&Head@2dda6444
map==java.util.stream.ReferencePipeline&Head@5e9f23b4
flatMap==aa
flatMap==bb
flatMap==cc
flatMap==dd
flatMap==ee
flatMap==ff
可以看出map就是将数组流直接返回,flatMap是将数组流中的每个元素都返回。flatMapToInt,flatMapToLong,flatMapToDouble类似,只不过返回的是对应的类型的流,此处不做演示。

distinct:将集合中的元素去重。
List<String> disList = Arrays.asList("aaa","ddd","bbb","ddd","aaa");
disList.stream()
.distinct()
.forEach(s-> System.out.println(s));
1
2
3
4
输出如下:

aaa
ddd
bbb
sorted:将集合中的元素排序。
List<Integer> integerList = Arrays.asList(1,2,3,4);
integerList.stream()
.sorted()
.forEach(s-> System.out.println(s));
1
2
3
4
输出如下:

1
2
3
4
可以按照自定义排序:

integerList.stream()
.sorted((s1,s2)->s2.compareTo(s1))
.forEach(s-> System.out.println(s));
1
2
3
输出如下:

4
3
2
1
peek:生成一个包含原Stream的所有元素的新Stream,同时会提供一个消费函数即引用的方法A,当Stream每个元素被消费的时候都会先执行新Stream给定的方法A。peek是中间操作,如果pee后没有最终操作,则peek不会执行。
integerList.stream()
.peek(s-> System.out.println("peek = "+s));
1
2
此时没有输出,代码改为:

integerList.stream()
.peek(s-> System.out.println("peek = "+s))
.forEach(s-> System.out.println("forEach = "+s));
1
2
3
输出如下:

peek = 1
forEach = 1
peek = 2
forEach = 2
peek = 3
forEach = 3
peek = 4
forEach = 4
limit:返回Stream的前n个元素。
integerList.stream()
.limit(1)
.forEach(s-> System.out.println(s));
1
2
3
输出为:

1
skip:删除Stream的前n个元素。
integerList.stream()
.skip(1)
.forEach(s-> System.out.println(s));
1
2
3
输出如下:

2
3
4
forEach:遍历Stream中的每个元素,前面每个例子都有使用,此处不再演示。
forEachOrdered:遍历Stream中的每个元素。
区别:
在串行流(stream)中没有区别,在并行流(parallelStream)中如果数据源是有序集合,forEachOrdered输出顺序与数据源中顺序一致,forEach则是乱序。
看下使用forEach:

integerList.stream()
.forEach(s-> System.out.println(s));
1
2
输出(多次测试,每次结果都不一样):

3
1
4
2
再看使用forEachOrdered:

integerList.parallelStream()
.forEachOrdered(s-> System.out.println(s));
1
2
输出(测试多次,每次都是这个结果,与integerList中的元素顺序一致):

2
1
3
4
toArray:将流转换为Object[]或者指定类型的数组。
Object[] array = integerList.stream().toArray();
String[] strArr = integerList.stream().toArray(String[]::new);
1
2
reduce:将集合中的每个元素聚合成一条数据。有三种情况:
reduce(BinaryOperator accumulator):此处需要一个参数,返回Optional对象:
Optional<Integer> reduce = integerList.stream().reduce((a, b) -> a + b);
1
reduce(T identity, BinaryOperator accumulator):此处需要两个参数,第一个参数为起始值,第二个参数为引用的方法。从起始值开始,每个元素执行一次引用的方法(方法引用的中的两个参数:第一个参数为上个元素执行方法引用的结果,第二个参数为当前元素)。
int integer = integerList.stream().reduce(5,(a, b) -> a + b);
System.out.println(integer);
1
2
输出为:

15
此例中使用起始值为5,对集合中每个元素求和,可以理解为:5+2+1+3+4=15。

reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner):此处需要三个参数。此方法用在并发流(parallelStream)中,启动多个子线程使用accumulator进行并行计算,最终使用combiner对子线程结果进行合并,返回identity类型的数据,看到有篇文章对这个解释比较清楚:java8中3个参数的reduce方法怎么理解?
collect:将流转换成集合或聚合元素。有两种情况。接受一个参数和接受三个参数(三个参数在并发流parallelStream中使用),此处介绍一个参数的情况,单个参数接受的参数类型为Collector,Collectors 类实现了很多归约操作,详见:java8之collector
List<Integer> collects = integerList.stream()
.filter(a -> a > 1)
.collect(Collectors.toList());
System.out.println(collects);
1
2
3
4
此处统计集合中大于1的元素并最终返回list。输出如下:

[2, 3, 4]
min:获取集合中最小值。
Integer min = integerList.stream()
.filter(a -> a > 1)
.min((Integer a, Integer b) -> a.compareTo(b))
.get();
System.out.println(min);
1
2
3
4
5
输出为:

2
max:获取集合中最大值。
Integer max = integerList.stream()
.filter(a -> a > 1)
.max((Integer a, Integer b) -> a.compareTo(b))
.get();
System.out.println(max);
1
2
3
4
5
输出为:

4
count:获取集合中元素个数
long count = integerList.stream()
.filter(a -> a > 1)
.count();
System.out.println(count);
1
2
3
4
输出为:

3
anyMatch: Stream 中任意一个元素符合传入的 predicate,返回 true
allMatch:Stream 中全部元素符合传入的 predicate,返回 true
noneMatch:Stream 中没有一个元素符合传入的 predicate,返回 true
boolean b = integerList.stream()
.anyMatch(s -> s > 0);
boolean b1 = integerList.stream()
.allMatch(s -> s > 0);
boolean b2 = integerList.stream()
.noneMatch(s -> s > 0);
System.out.println("anyMatch = " + b);
System.out.println("allMatch = " + b1);
System.out.println("noneMatch = " + b2);
1
2
3
4
5
6
7
8
9
输出:

anyMatch = true
allMatch = true
noneMatch = false
findFirst:如果数据源是有序集合,返回Stream 中第一个元素的Optional对象,如果是无序集合,则返回Stream 中任意一个元素的Optional对象。
Integer first = integerList.stream()
.findFirst()
.get();
System.out.println(first);
1
2
3
4
输出为:

2
findAny:返回Stream 中任意一个元素的Optional对象。
Integer any = integerList.stream()
.findAny()
.get();
System.out.println(any);
1
2
3
4
输出为:

2
Stream还有几个静态方法,返回都是Stream对象。
静态方法如下:builder(返回Builder对象)、empty、of、iterate、generate、concat。
builder:返回一个Builder对象,Builder对象在调用build()返回Stream对象。
empty:返回一个空的有序的Stream对象。
of:返回包含单个元素的有序的Stream对象。
iterate:返回一个无限元素的有序的Stream对象。需要两个参数,第一个参数为初始值,第二个参数为要引用的方法,然后会通过递归循环调用引用的方法。

Stream.iterate(2,s->s+s)
.limit(10)
.forEach(s-> System.out.println(s));
1
2
3
输出为:

2
4
8
16
32
64
128
256
512
1024
generate:返回一个无限元素的无序的的Stream对象。需要一个参数,参数为引用的方法,然后会通过循环调用引用的方法来生成元素,常用于生成常量Stream和随机元素Stream。
concat:将两个Stream连接成一个Stream。需要两个Stream作为参数,如果两个Stream都是有序的并且无论参数Stream是否是并行Stream,得到的都是有序的Stream。输出元素顺序为先输出第一个Stream的元素,然后输出第二个Stream的元素。当结果Stream关闭时候,两个参数Stream同时关闭。

Stream.concat(integerList.stream(),disList.stream())
.forEach(s-> System.out.println(s));
1
2
输出为:

2
1
3
4
11
aaa
ddd
33
bbb
ddd
aaa
————————————————
版权声明:本文为CSDN博主「昵称2019」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/bluuusea/article/details/79967039

JAVA8新特性--集合流操作Stream的更多相关文章

  1. Java8 新特性之集合操作Stream

    Java8 新特性之集合操作Stream Stream简介 Java 8引入了全新的Stream API.这里的Stream和I/O流不同,它更像具有Iterable的集合类,但行为和集合类又有所不同 ...

  2. Java8 新特性之Stream----java.util.stream

    这个包主要提供元素的streams函数操作,比如对collections的map,reduce. 例如: int sum = widgets.stream() .filter(b -> b.ge ...

  3. Java8新特性之方法引用&Stream流

    Java8新特性 方法引用 前言 什么是函数式接口 只包含一个抽象方法的接口,称为函数式接口. 可以通过 Lambda 表达式来创建该接口的对象.(若 Lambda 表达式抛出一个受检异常(即:非运行 ...

  4. Java8新特性(1)—— Stream集合运算流入门学习

    废话,写在前面 好久没写博客了,懒了,以后自觉写写博客,每周两三篇吧! 简单记录自己的学习经历,算是对自己的一点小小的督促! Java8的新特性很多,比如流处理在工作中看到很多的地方都在用,是时候扔掉 ...

  5. Java8新特性第3章(Stream API)

    Stream作为Java8的新特性之一,他与Java IO包中的InputStream和OutputStream完全不是一个概念.Java8中的Stream是对集合功能的一种增强,主要用于对集合对象进 ...

  6. Java8 新特性2——强大的Stream API

    强大的Stream API Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找.过滤和映射数据等操作.简而言之,Stream API 提供 ...

  7. java8新特性-lambda表达式和stream API的简单使用

    一.为什么使用lambda Lambda 是一个 匿名函数,我们可以把 Lambda表达式理解为是 一段可以传递的代码(将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码风 ...

  8. Java8 新特性 Stream 非短路终端操作

    非短路终端操作 Java8 新特性 Stream 练习实例 非短路终端操作,就是所有的元素都遍厉完,直到最后才结束.用来收集成自己想要的数据. 方法有: 遍厉 forEach 归约 reduce 最大 ...

  9. Java8 新特性 Stream 短路终端操作

    短路终端操作 Java8 新特性 Stream 练习实例 传入一个谓词,返回传为boolean,如果符合条件,则直接结束流. 匹配所有 allMatch 任意匹配 anymMatch 不匹配 none ...

随机推荐

  1. bacula备份工具

    源码下载:http://www.bacula.org bacula适合数据业务量巨大,每天都在迅速增长,还需要以tar打包方式进行低级备份而且没有异地容灾策略.Bacula是一个完美的增量备份功能,同 ...

  2. [b0042] python 归纳 (二七)_gui_tkinter_基本使用

    # -*- coding: utf-8 -*- """ 学习 Tkinter画图基本控件使用 逻辑: 放几个 输入控件.点击按钮,将输入控件内容打印出来 使用: 1. 创 ...

  3. FileSizeLimitExceededException

    org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException 很明显,这异常的意思是文件大小 ...

  4. 详解YUV数据格式

    我们在讲 FFmpeg 系列的时候,有提到 YUV 的.其中包括YUV播放器.简单的YUV格式介绍. 一.YUV简介 YUV,是一种颜色编码方法.常使用在各个影像处理元件中. YUV在对照片或影片编码 ...

  5. 使用Socket下载图片

    Socket下载一张图片 Socket下载一页图片 Socket下载一张图片 在百度搜索头像,挑一张 复制图片的路径打开,并保存这个url 把这个url的域名和路径分开 首先导入socket模块 第一 ...

  6. 6.3 使用Spark SQL读写数据库

    Spark SQL可以支持Parquet.JSON.Hive等数据源,并且可以通过JDBC连接外部数据源 一.通过JDBC连接数据库 1.准备工作 ubuntu安装mysql教程 在Linux中启动M ...

  7. 【BZOJ1443】[JSOI2009]游戏Game(二分图+博弈)

    BZOJ 题意: 给出一个\(n*m\)的网格,其中有一些障碍点. 现在两个人玩游戏,首先先手选定一个点,然后从后手开始轮流移动,不能移动者即输掉这次游戏. 规定不能移动到那些之前已经到过的格子上. ...

  8. .gclient文件

    //注意以.开头的文件名在linux下都是隐藏文件,需要使用ll 或者ls -all 才可以查看. .gclient文件必须有,否则会报类似下面的错误: Traceback (most recent ...

  9. NOIP2007 奖学金 结构体排序

    是结构体排序的练习题,可供选手们巩固结构体排序的一些相关内容. 关于结构体排序 1.结构体定义 struct student { int num,a,b,c,sum; }p[]; 2.结构体初始化 ; ...

  10. C++ 异或运算及其应用

    前置知识: 1.一个整数自己跟自己异或,结果为0   //因为异或的法则为,相同为0,不同为1,注意这里所说的都是二进制位. 2.任意一个整数跟0异或,结果为本身. //因为1异或0得1,0异或0,得 ...