Java8实战读书笔记-第4章 引入流

4.1 流是什么

流是Java API的新成员,它允许你以声明性方式处理数据集合(通过查询语句来表达,而不是临时编写一个实现)。就现在来说,你可以把它们看成遍历数据集的高级迭代器。此外,流还可以透明地并行处理,你无需写任何多线程代码了!

4.2 流简介

流:从支持数据处理操作的源生成的元素序列

List<String> list = menu.stream().filter(e -> e.getCalories() < 400 && e.isVegetarian()).map(Dish::getName).limit(3L).collect(toList());

menu是一个List集合数据;
通过stream()转换成流;
filter,map,limit都是对流的一系列数据处理,称为中间操作;
最后的collect(toList())把流转换成List,称为终端操作;

在调用collect之前,没有任何结果产生,实际上根本就没有从menu里选择元素。你可以这么理解:链中的方法调用都在排队等待,直到调用collect。

4.3 流与集合

集合与流之间的差异就在于什么时候进行计算。

集合可以删除或添加元素;而流则是固定的数据结构,其元素是按需计算

从另一个角度来说,流就像是一个延迟创建的集合:只有在消费者要求的时候才会计算值(用管理学的话说这就是需求驱动,甚至是实时制造)。

比如说存在DVD里的电影,这就是一个集合(也许是字节,也许是帧,这个无所谓),因为它包含了整个数据结构。现在再来想想在互联网上通过视频流看同样的电影。现在这是一个流(字节流或帧流)。流媒体视频播放器只要提前下载用户观看位置的那几帧就可以了,这样不用等到流中大部分值计算出来,你就可以显示流的开始部分了(想想观看直播足球赛)。特别要注意,视频播放器可能没有将整个流作为集合,保存所需要的内存缓冲区——而且要是非得等到最后一帧出现才能开始看,那等待的时间就太长了。出于实现的考虑,你也可以让视频播放器把流的一部分缓存在集合里,但和概念上的差异不是一回事。

4.3.1 只能遍历一次

流只能遍历一次。遍历完之后,我们就说这个流已经被消费掉了。你可以从原始数据源那里再获得一个新的流来重新遍历一遍。

4.3.2 遍历数据方式的区别

Collection接口的迭代属于外部迭代;
Stream库使用内部迭代.

//集合:用外部的迭代器做外部迭代
List<String> names = new ArrayList<>();
for(Dish d: menu){ ←─显式顺序迭代菜单列表
 names.add(d.getName()); ←─提取名称并将其添加到累加器
}

//流:内部迭代
List<String> names = menu.stream()
 .map(Dish::getName) ←─用getName 方法参数化map,提取菜名
 .collect(toList()); ←─开始执行操作流水线;没有迭代!

4.4 流操作

4.4.1 中间操作
List<String> names =
   menu.stream()
       .filter(d -> {
            System.out.println("filtering" + d.getName());
            return d.getCalories() > 300;
           }) ←─打印当前筛选的菜肴
       .map(d -> {
            System.out.println("mapping" + d.getName());
            return d.getName();
           }) ←─提取菜名时打印出来
       .limit(3)
       .collect(toList());
System.out.println(names);

//此代码执行时将打印:
filtering pork
mapping pork
filtering beef
mapping beef
filtering chicken
mapping chicken
[pork, beef, chicken]

你会发现,有好几种优化利用了流的延迟性质。第一,尽管很多菜的热量都高于300卡路里,但只选出了前三个!这是因为limit操作和一种称为短路的技巧。第二,尽管filter和map是两个独立的操作,但它们合并到同一次遍历中了(我们把这种技术叫作循环合并)。

4.4.2 终端操作

终端操作会从流的流水线生成结果。其结果是任何不是流的值,比如List、Integer,甚至void。

4.4.3 使用流

流的使用一般包括三件事:
一个数据源(如集合)来执行一个查询;
一个中间操作链,形成一条流的流水线;
一个终端操作,执行流水线,并能生成结果。

4.5 小结

流是“从支持数据处理操作的源生成的一系列元素”。
流利用内部迭代:迭代通过filter、map、sorted等操作被抽象掉了。
流操作有两类:中间操作和终端操作。
filter和map等中间操作会返回一个流,并可以链接在一起。可以用它们来设置一条流水线,但并不会生成任何结果。
forEach和count等终端操作会返回一个非流的值,并处理流水线以返回结果。
流中的元素是按需计算的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值