Stream流的首次使用

53 阅读2分钟

什么是 Stream?

Stream(流)是一个来自数据源的元素队列并支持聚合操作

  • 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
  • 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
  • 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。

和以前的Collection操作不同, Stream操作还有两个基础的特征:

  • Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
  • 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。

之前学习java8新特性的时候,了解到有Stream流这个东西,知道了他的基本概念和用法,但是还压根不知道那里能用上。然后我在前几天的一次sql语句的编写上遇到了问题,大致是需要有两次查询数据库的操作,这两次的结果一次返回,并且第一次查询到的字段中的某一个字段是第二次查询操作的条件之一。

我首先想到的是sql语句的嵌套写法,但是当我写的时候才发现很难实现。要么我没法返回所有我想要的结果,要么我没办法使用之前的条件,总之,就是我以我现有的sql知识,没办法满足我的需要,然后我亲爱的舍长给我演示了如何使用Stream流来操作第一次查询到的结果,并对其进行二次查询处理封装返回,这一套下来Stream流在我心中一下就高大上了!

使用过程如下:

LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Comment::getVideoId, videoId)
      .eq(Comment::getCommentLevel, 1);
Page<Comment> page = new Page<>(nodePage, pageSize);
commentMapper.selectPage(page, queryWrapper);//得到第一次的查询结果

Page<CommentDto> dtoPage=new Page<>();
BeanUtil.copyProperties(page,dtoPage,"records");
List<Comment> pageRecords = page.getRecords();
List<CommentDto> dtos = pageRecords.stream().map((item) -> {//对查询结果的list集合使用Strem流的map方法处理其中的所有元素
    CommentDto commentDto = new CommentDto();
    BeanUtil.copyProperties(item, commentDto);
    LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
    wrapper.eq(Comment::getCommentId, commentDto.getId())
        .eq(Comment::getCommentLevel, 2);//使用第一次查询到的结果进行二次查询
commentDto.setCommentReplyNumber(commentMapper.selectCount(wrapper));
return commentDto;//将两次查询到的结果进行封装返回
}).collect(Collectors.toList());//将处理过的元素转成一个新的集合
dtoPage.setRecords(dtos);//封装到page对象中

其中使用的是mybaits-plus。

通过这个案例,虽说不能让我熟练的掌握Stream流的使用,但是对我理解Stream流还是有很大帮助的,特此记录一下,继续加油。