Java 8 Streams
最近两周被平台组指名道姓拉去当了两周的苦力,写业务层代码,因为逻辑比较复杂数据输入比较多样,所以导致使用集合的概率很高,且常常伴随着过滤、排序等操作,继而用到了很多Streams提供的方法,遂做个简单记录。
Streams
Stream是Java 8中引入的新的抽象层,它提供了一些类似SQL语句的声明性方式处理数据。
流操作分为中间操作和最终操作,元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。 流管道由一个源(例如Collection,数组,生成器函数或I / O通道)组成; 随后是零个或多个中间操作,例如Stream.filter或Stream.map; 以及诸如Stream.forEach或Stream.reduce之类的终端操作。
即将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道中插入节点上进行处理, 比如筛选, 排序,聚合等。
当然为什么喜欢用它还是因为Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。会让代码看起来更加简洁当然通常也会更加高效。
API
如上图api很多,其中又可以按照最开始说的分为中间操作、最终操作两类,中间(Intermediate)操作是可以零个或者多个但是最终(Terminal)操作只能有一个,能力有限我就列举一下我常用的。
可能我们需要注意的一个概念:因为一个 Stream 可以进行多次中间操作,那是不是就会对 Stream 的每个元素进行转换多次,即时间复杂度就是 N(转换次数)个 ?其实不是这样的,转换操作都是 lazy 的,多个转换操作只会在 Terminal 操作的时候融合起来,一次循环完成。
中间操作(intermediate operation)
API | 说明 |
---|---|
filter | 用于按指定条件过滤元素 |
map | map方法将每个元素映射到其相应的结果,通常用于list转换为map |
limit | limit返回流中的前N个元素,同SQL的limit |
sorted | 对Stream中的元素进行排序 |
distinct | 删除重复项 |
最终操作(terminal operation)
API | 说明 |
---|---|
forEach | 迭代Stream中的元素 |
sum | 对Stream中的元素求和 |
collect | 可以接受各种参数并将流元素累加成集合 |
reduce | 这个方法的主要作用是把 Stream 元素组合起来。它提供一个起始值(种子),然后依照运算规则(BinaryOperator),和前面 Stream 的第一个、第二个、第 n 个元素组合。其实sum等这类也可以说是reduce。 |
max | 获取Stream中符合条件的最大值 |
findAny | 这是一个 termimal 操作,它总是返回 Stream 的符合条件的元素,或者空。注意它的返回值类型是Optional(为了避免空指针)。 |
anyMatch | Stream 中只要有一个元素符合传入的 条件。 |
示例
列出几个工作中实践的例子
1 | // 用于按指定条件过滤元素并且把符合条件的添加到指定的集合 |
1 | // 拿输入的id到stream中比较是否存在,如果不存在则返回null |
1 | // 两个集合中,集合B中找到符合集合A中的数据,最终得到符合条件的元素集合 |
1 | // checkList的元素作为IpV4Ranges中toRange方法的参数,最终把toRange返回值转换为集合 |
1 | // Alarm的list集合,转换为map,key为Alarm的appId,value为Alarm |
1 | // 根据状态排序,如果状态一样按照名称排序 |
1 | // 判断输入参数里是否存在任意一个满足haveXssCondition |
最后
很显然我这篇仅仅是一个简单的记录文档,如果需要深入了解,还是系统的看相关的文档和源码。而且我主要用的是stream其实还有parallelStream,有兴趣的大家可以看看。