Redian新闻
>
聊一聊Java中的Steam流

聊一聊Java中的Steam流

公众号新闻

来源 | OSCHINA 社区

作者 | 京东云开发者-京东物流 王辰玮

原文链接:https://my.oschina.net/u/4090830/blog/10087460

1 引言

在我们的日常编程任务中,对于集合的制造和处理是必不可少的。当我们需要对于集合进行分组或查找的操作时,需要用迭代器对于集合进行操作,而当我们需要处理的数据量很大的时候,为了提高性能,就需要使用到并行处理,这样的处理方式是很复杂的。流可以帮助开发者节约宝贵的时间,让以上的事情变得轻松。

2 流简介

流到底是什么呢?简要的定义为 “从支持数据处理操作的源生成的元素序列”,接下来对于这个定义进行简要分析。

2.1 支持数据处理操作

流的数据处理操作和数据库的可以声明式的指定分组或查找等功能支持类似,和函数式编程的思想一致,如 filter、map、reduce、find、match、sort 等操作,这些流操作可以串行执行,也可以并行执行。

2.2 源

流会使用一个提供数据的源,可以通过三种方式来创建对象流,一种是由集合对象创建流:
List<Integer> list = Arrays.asList(111,222,333);
Stream<Integer> stream = list.stream();

一种是由数组创建流:

IntStream stream = Arrays.stream(new int(){111,222,333});

一种是由静态方法 Stream.of () 创建流,底层还是 Arrays.stream ():

Stream<Integer> stream = Stream.of(111, 222, 333);
Stream stream = Stream.of(111, 222, 333);
从有序集合生成流时会保留原有的顺序。由列表生成的流,其元素顺序与列表一致。
还有两种特殊的流:
  • 空流:Stream.empty ()

  • 无限流:Stream.genarate ()

2.3 元素序列

流也可以和集合一样访问包含特定的元素类型的一组有序值,但是它们的主要目的不一样,集合的主要目的是在于存储和访问元素,流的主要目的在于表达计算。

3 流的思想

流式思想和生产中的流水线具有异曲同工之妙,很多流模型都会返回一个流,这些模型都只负责它所需要做的事情,并不需要格外的内存空间来存储处理的结果。这些流模型可以被链接起来形成一个大的流水线,我们在这个过程中不关注中间步骤的数据被如何处理,只需要使用整个流水线处理后的结果。接下来的代码可以体现这种思想,代码中以商品为例,我们要筛选出商品中体积大于 200 的前两个商品的名字。
首先是商品类的定义:
public class Goods {
private final String Name;
private final Integer Volume;

public Goods(String name, Integer volume) {
Name = name;
Volume = volume;
}
public String getName() {
return Name;
}
public Integer getVolume() {
return Volume;
}
}

接下来是商品集合的定义:

List<Goods> goods = Arrays.asList(new Goods("土豆",10),
new Goods("冰箱",900),new Goods("办公椅",300));

接下来获取我们想要的结果:

List<String> twofoods = goods.stream()//获取流
.filter(goods1 -> goods1.getVolume()>200)//筛选商品体积大于200的
.map(Goods::getName)//获取商品名称
.limit(2)//筛选头两个商品
.collect(Collectors.toList());//将结果保存在list中
这样看来,通过流来处理我们的特定需求,是不是比使用集合的迭代要方便很多呢?

4 流处理的特性

  • 不存储数据

  • 不会改变数据源

  • 只可被使用一次

这里我们使用一个测试类 StreamCharacteristic 来验证流处理的以上特性:
import org.springframework.util.Assert;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StreamCharacteristic {
public void test1(){
List<Integer> list = Arrays.asList(1,2,2,5,6,9);
list.stream().distinct();
System.out.println(list.size());
}
public void test2(){
List<String> list = Arrays.asList("wms", "KA", "5.0");
Stream<String> stream = list.stream();
stream.forEach(System.out::println);
stream.forEach(System.out::println);
}
}
test1 () 中的结果为 6,尽管我们对于 list 对象所生成的 Stream 流做了去重操作 distinct (),但是不影响数据源 list。
test2 () 中调用了两次 stream.forEach 方法来打印每一个单词,第二次调用时,抛出了一个 “java.lang.IllegalStateException” 异常:“stream has already been operated upon or closed”。这说明流不存储数据,遍历完后这个流已经被消费掉了,而且流不可以重复使用。

5 流操作与流的使用

将所有的流操作连接起来可以组合成一个管道,管道有两类操作:中间操作和终端操作。
StreamAPI 常用的中间操作有:filter,map,limit,sorted,distinct。
StreamAPI 常用的终端操作有:forEach,count,collect。
在使用流的时候,主要需要三个要素:一个用来执行查询的数据源,用来形成一条流的流水线的中间操作链,一个能够执行流水线并能生成结果的终端操作。
下图展示了流的整个操作流程:

6 总结

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

  • 流的思想类似于生产中的流水线

  • 流不存储数据,不改变数据源,只能被改变一次

  • 流的操作主要分为中间操作和终端操作两大类

往期推荐



周热点 | 2023.07.03-2023.07.09
Python之父“摇人”来搞掉GIL,Meta果断出手

爱奇艺客户端 “白嫖” 电视机,后台满速上传



这里有最新开源资讯、软件更新、技术干货等内容

点这里 ↓↓↓ 记得 关注✔ 标星⭐ 哦


微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
聊一聊:在Steam里,你游戏时长最高的是啥游戏?聊一聊:你为爱好做的最大一笔投资是啥?人民币,美元双系统风险及解决的可能方案聊一聊:聊天时哪些话会让你血压升高?聊一聊:你是怎么给妈妈过母亲节的?聊一聊:你玩过最有意思的双人游戏是啥?会 java 8 stream流就会大数据!聊一聊:你在什么情况下会换手机壳?𝐂𝐚𝐥𝐧𝐢𝐊𝐞𝐚𝐧双皮奶内衣裤,软弹有度,上身0束缚~妈妈看到我和男友的聊天记录后,骂我“贱”!想和妈妈坐下来聊一聊怎么这么难?聊一聊续航较好的intel笔记本希腊沃洛斯 (Volos),迷人夜幕千箴言万球炼(5) 嫉妒世间常态,磨砺锻炼能耐聊一聊:你最近一条发出去的短信是什么?聊一聊:除了微信,你手机里啥应用最占地方?【𝐂𝐚𝐥𝐧𝐢𝐊𝐞𝐚𝐧双皮奶无痕内裤】49元三条!巨巨巨好穿 !!简直就是辣妹顶配,食品级冰箱收纳盒【一日团】聊一聊:你用过什么有意思的快递收件名?聊一聊:你们公司上下班是咋打卡的?黄春菊,朝气蓬勃偶兴聊一聊:你的互联网减速带是啥?聊一聊:讲讲你印象最深的一次团建?聊一聊:哪些APP你会经常互相点错?聊一聊:你坚持最久的爱好是啥?聊一聊一个定语从句难点知识聊一聊:你看过啥印象深刻的爽文?聊一聊:你用过续航最久的数码产品是啥?[评测]CoolerMaster MasterAir MA824 Stealth 评测聊一聊:你想对刚高考完的考生说点啥?聊一聊分布式系统中的时空观构建再次聊一聊周期股买在低位的问题聊一聊:你把哪些软件当朋友圈用?聊一聊:你因为哪个游戏买的Switch?聊一聊:你目前最期待的一件事?跟马红漫聊一聊:人工智能很火,但跟你有什么关系?
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。