Java-stream(1) Stream基本概念 & Stream接口
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java-stream(1) Stream基本概念 & Stream接口,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5837字,纯文字阅读大概需要9分钟。
内容图文
![Java-stream(1) Stream基本概念 & Stream接口](/upload/InfoBanner/zyjiaocheng/621/6d4fa1e90b294e0ebd0ce35be9ac6eed.jpg)
Java8 集合中的 Stream 相当于高级版的 Iterator,他可以通过 Lambda 表达式对集合进行各种非常便利、高效的聚合操作(Aggregate Operation),或者大批量数据操作 (Bulk Data Operation)
Stream 就如同一个迭代器(Iterator),单向,不可往复,数据只能遍历一次,遍历过一次后即用尽了,就好比流水从面前流过,一去不复返
函数式的解决方案解开了代码细节和业务逻辑的耦合,类似于sql语句,表达的是"要做什么"而不是"如何去做",使程序员可以更加专注于业务逻辑,写出易于理解和维护的代码
一、基本概念
1.1 Stream 操作分类
(图片来源:极客时间-《java性能调优实战》第6讲)
我们通常还会将中间操作称为懒操作,也正是由这种懒操作结合终结操作、数据源构成的处理管道(Pipeline),实现了 Stream 的高效
1.2 Stream 主要架构类关系
二、Stream接口
2.1 概述(接口文档)
什么是stream?
是一个支持串行/并行的聚合操作的元素队列。为了进行计算,组建了一个 stream管道(pipeline),一个流管道由一个源(可能是数组、集合、构造函数、I/O流等)、0到多个中间操作(intermediate operations)和终结操作(terminal operation)组成。
stream有哪些特点?
-》流是惰性的,只有在启动终结操作时才对源数据执行计算,只执行中间操作的时候是不会触发流计算的,并且仅在需要时才使用源元素。
-》集合和stream虽然在表面有一些相似之处,但是他两的侧重点是不一样的。集合主要是对元素的管理和访问。相比之下,stream不提供直接访问或者操作元素的方法,而是关注于声明性地描述元素的聚合和计算操作,然而,如果所提供的流操作不提供所需的功能,则可以使用这些操作来执行受控遍历。
-》如果stram popeline在操作过程中对源数据进行了修改操作会导致不可预知的报错
-》参数会去调用函数接口(Function)或者通常使用lambda表达式引用,所以这些参数必须“非空”
-》在stream中数据从源到终结只会被执行一次,不可以重复操作数据,如果有重复使用的情况会抛出 IllegalStateException 异常(由于一些流操作可能返回其接收器而不是新的流对象,因此可能不可能在所有情况下检测重用)
-》stream有一个close()方法,还有实现了AutoCloseable接口(BaseStream继承),但是大多数stream实例在使用完后不需要关闭,通常,只有源为IO通道的流才需要关闭。大多数流由集合、数组或生成器组成,这些函数不需要特殊的资源管理
-》流管道可以串行执行数据,可以并行执行,通过paralle()方法去选择不同的执行方式
2.2 一些常用方法
filter()
作用:中间-无状态操作,对流数据进行过滤,返回满足入参条件的数据
入参:Predicate<? super T> predicate 数据的过滤条件
出参:Stream:返回一个新的符合条件的Stream 流数据
举例:过滤出 小于3 的元素
public static void main(String[] args) {
List<Integer> list = Stream.of(1, 2, 3, 4).filter(p -> p < 3).collect(Collectors.toList());
System.out.println(list);
}
输出:[1, 2]
map()
作用:中间-无状态操作,内部通过函数的形式对流数据进行一系列操作,返回函数结果集
入参:Function<? super T, ? extends R> mapper:操作函数
出参:Stream :返回一个新的函数处理结果集的流数据
举例:将每个元素 +1
public static void main(String[] args) {
List<Integer> list = Stream.of(1, 2, 3, 4).map(p -> p + 1).collect(Collectors.toList());
System.out.println(list);
}
输出:[2, 3, 4, 5]
distinct()
作用:
中间-有状态操作,对当前流数据进行元素去重操作(通过equals()方法判断),返回一个由不同元素组成的流数据,对于有序流,不同元素的选择是稳定的(对于重复的元素,保留遇到的第一个出现的元素),对于无序流,不提供稳定性保证。如果是在并行管道(paralle pipeline)中,保持流数据的排序稳定性是比较昂贵的(要求当前操作充当一个完整的屏障,具有大量的缓冲开销)。
一般情况下业务代码中是不需要保持排序稳定性的,是有无需流数据源(generate())或者通过unordered()方法删除排序约束可以更好的提高在并行管道中的执行效率。如果必须要做到排序的稳定性,最好切换到顺序执行来提高性能。
入参:无入参,对当前流数据进行去重操作(this)
出参:Stream:去重后的一个新的流数据
举例:将元素去重
public static void main(String[] args) {
List<Integer> list = Stream.of(1, 2, 4, 4).distinct().collect(Collectors.toList());
System.out.println(list);
}
sorted()
作用:中间-有状态操作,对当前流数据进行自然排序(按照compareTo()规则排序),如果当前流数据没有实现Comparable接口的话会抛出 ClassCastException 异常。同样,对于有序流,排序是稳定的。对于无序流,不提供稳定性保证。
入参:无入参,对当前流数据进行排序操作(this)
出参:Stream:排序后的一个新的流数据
备注:该方法还提供了重载方法,入参为Comparator接口对象,这个方法根据Comparator提供的规则来进行排序。
举例:对元素进行排序
public static void main(String[] args) {
List<Integer> list = Stream.of(1, 3, 4, 2).sorted().collect(Collectors.toList());
System.out.println(list);
}
输出:[1, 2, 3, 4]
peek()
作用:
中间-无状态操作,对流数据进行一些操作,但是它只是对Stream中的元素进行某些操作(比如输出之类),但是操作之后的数据并不返回到Stream中,所以返回的还是原来的元素,不会像map()一样返回一个新的类型的流数据,通常会作为debug打印中间数据使用。
这里要注意的是,如果流数据是个实体对象的话,peek()可以通过调用实体对象的setter方法对其属性值进行改变——也就是说peek()可会流数据进行修改操作,其他方法是不具备的(会创建一个新的对象作为返回结果)。
入参:Consumer<? super T> action:对当前流数据的操作函数
出参:Stream:当前流数据
备注:map()和peek()的区别详解移步:https://www.cnblogs.com/flydean/p/java-8-stream-peek.html
举例:输出每个元素值
public static void main(String[] args) {
List<Integer> list = Stream.of(1, 2, 3, 4).peek(p -> System.out.println("输出:p = " + p)).collect(Collectors.toList());
System.out.println(list);
}
输出:
输出:p = 1
输出:p = 2
输出:p = 3
输出:p = 4
[1, 2, 3, 4]
此外stream接口还提供了例如limit(限定流数据的长度),min(返回小元素),max(返回最大元素)等方法,这里就不一一展开说明了,其原理都是相似的。
三、扩展
扩展一:Predicate接口
Predicate是个断言式接口,其参数是<T,boolean>,也就是给一个参数T,返回boolean类型的结果。跟Function一样,Predicate的具体实现也是根据传入的lambda表达式来决定的。
boolean test(T t);
扩展二:排序稳定性
假定在一个待排序的序列中,存在多个相同的元素,若经过排序操作,这些元素的相对次序不变,则成为这种算法是稳定的,否则就是不稳定的。
eg. 在原序列中,node1==node2 && node1在node2之前
排序后:如node1在node2之前并且无论执行多少次都是这样,则认为这种算法是稳定的,否则是不稳定的。
写在最后 欢迎关注微信公众号【小肖爱吃肉】和你一起记录生活的小美好
内容总结
以上是互联网集市为您收集整理的Java-stream(1) Stream基本概念 & Stream接口全部内容,希望文章能够帮你解决Java-stream(1) Stream基本概念 & Stream接口所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。