惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 叶小钗
O
OpenAI News
V
V2EX
大猫的无限游戏
大猫的无限游戏
博客园 - 聂微东
S
Schneier on Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
小众软件
小众软件
L
LINUX DO - 热门话题
C
Cybersecurity and Infrastructure Security Agency CISA
博客园 - Franky
Security Latest
Security Latest
S
SegmentFault 最新的问题
Project Zero
Project Zero
Spread Privacy
Spread Privacy
K
Kaspersky official blog
J
Java Code Geeks
V
Vulnerabilities – Threatpost
C
Cisco Blogs
C
CERT Recently Published Vulnerability Notes
月光博客
月光博客
T
The Exploit Database - CXSecurity.com
L
Lohrmann on Cybersecurity
人人都是产品经理
人人都是产品经理
博客园 - 三生石上(FineUI控件)
Scott Helme
Scott Helme
WordPress大学
WordPress大学
量子位
T
Threat Research - Cisco Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
宝玉的分享
宝玉的分享
Hugging Face - Blog
Hugging Face - Blog
AWS News Blog
AWS News Blog
Help Net Security
Help Net Security
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Simon Willison's Weblog
Simon Willison's Weblog
S
Secure Thoughts
博客园 - 【当耐特】
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
V
Visual Studio Blog
Last Week in AI
Last Week in AI
T
Tailwind CSS Blog
腾讯CDC
Cyberwarzone
Cyberwarzone
IT之家
IT之家
GbyAI
GbyAI
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
云风的 BLOG
云风的 BLOG
T
Troy Hunt's Blog
D
Docker

技术改变视野

为程序员、设计师打造的摸鱼社区:摸鱼派! - 技术改变视野 大白话 | Java初学指♂男:“说说初学的误区与死结”( 壹 | 反射与Field ) - 技术改变视野 大白话之耦合性:什么是耦合性和内聚性?用编程语言实例讲解! - 技术改变视野 🎨 适用于 Solo / Bolo 的清新高级主题 —— Sakura | 移植自 WordPress 主题 - 技术改变视野 我在 GitHub 上的开源项目 - 技术改变视野 为IDEA/Git配置GPG密钥,点亮GitHub Verified Commit标识 - 技术改变视野 从 SpringMVC 转为使用 SpringBoot —— 手把手带你使用 Intellij IDEA 最快速地搭建 SpringBoot+MyBatis(无 XML)+Thymeleaf - 技术改变视野 无题 - 技术改变视野 年轻人的第一辆京牌电动车 - 技术改变视野 我们忙碌且漫长的一生,有多久是为自己而活? - 技术改变视野 一个最简单的实例理解Semaphore在Java中的作用 - 技术改变视野 说说《后浪》 - 技术改变视野 离线使用 Google Fonts:让你的网站更精致 | goofoffline 神器,一键下载生成离线字体库! - 技术改变视野 实例带你学会简单的Java Thread多线程 - 技术改变视野 一个实例理解Java的接口(interface)用处与用法 - 技术改变视野 一个实例带你理解JavaBean - 技术改变视野 WebFilter-SpringBoot过滤器注解实例讲解 - 技术改变视野 实例带你搞懂Java多线程&&线程池之(壹):线程池与多线程的关系和区别 - 技术改变视野 实例带你搞懂Java多线程&&线程池之(贰):简单的线程池应用 - 技术改变视野 实例带你获取多线程Thread的返回值之 (壹) - Callable的运行 - 技术改变视野 实例带你获取多线程Thread的返回值之 (贰) - Callable配合线程池返回数据 - 技术改变视野 一个实例理解Java Runnable多线程用处与用法 - 技术改变视野 从零开始OpenSSL之 (壹) - 使用genrsa、rsa、rsautl生成公私钥 - 技术改变视野 从零开始 OpenSSL 之 (贰) - 使用 rsautl 解密文件 - 技术改变视野 大白话之Docker(壹):快速入门&&简单官方实例 - 技术改变视野 大白话之Docker(贰):简单部署一个Tomcat服务并发布内容 - 技术改变视野 大白话之从零讲解DVWA(壹)-SQL注入(SQL Injection) Low Level - 技术改变视野 大白话之从零讲解DVWA(贰)-SQL注入(SQL Injection) Medium/High Level - 技术改变视野 Java日志插件-Slog4J下载 - 技术改变视野 大白话之必会Java Atomic | 线程一点也不安全(一):比自增和synchronized更快速、靠谱的原子操作(调用C语言) - 技术改变视野 Log-MySQL root用户登录后无法查看数据库全部表/正常访问数据库 Access denied for user 'root'@'localhost' to database - 技术改变视野 大白话之Docker(叁):制作一个运行Tomcat服务端的Docker镜像 - 技术改变视野 Github仅保留指定文件/文件夹当前Commit,删除所有历史记录,清除「敏感信息」 - 技术改变视野 将Tomcat、MySQL从Linux迁移到Windows的心路历程(干货):令人恐惧的字符编码 - 技术改变视野 Spring: java.lang.NoSuchMethodError: clearCache | ClassNotFoundException | Error during artifact deployment 思路及解决办法 - 技术改变视野 大白话之Java反射-初学最迷的概念:能干啥?咋用? - 技术改变视野 大白话之Java面向接口编程:最“正经”的中文实例讲解,看不懂来打我! - 技术改变视野 大白话 | 课堂实践:使用Iterator对数组进行遍历 - 技术改变视野 大白话之fail-fast | fail-safe:为什么会有这个机制?它有什么作用? - 技术改变视野 刨根问底 | 大白话:在使用注解后,框架是怎么知道你哪个方法使用了注解的?用@RequestMapping注解举例详解! - 技术改变视野 大白话之必会Java Atomic | 线程一点也不安全(二):Atomic的ABA问题会导致什么情况?如何解决? - 技术改变视野 随笔 | 奇淫技巧 | Java:记return和短路运算符的妙用 - 技术改变视野 随笔 | Tomcat:续-从Linux迁移到Windows编码问题彻底解决 - 技术改变视野 大白话之AutoClosable接口 | try-with-resources:JDK1.7的新特性,提高重复回收效率 - 技术改变视野 大白话之Java多线程join方法:开局一张图,试学一分钟,你就费和我一样,理解介个方法 - 技术改变视野 Java 困扰三周の问题:使用byte[]或skip()方法读取字节流Stream文件尾部多/少/缺字节解决方法 - 技术改变视野 大白话之Java级联调用:一个类,一条语句,同时调用好几个方法,串成一串 - 技术改变视野
大白话之Java Stream流:将类数组流化,便捷批量修改,通俗讲解! - 技术改变视野
adlered · 2019-12-08 · via 技术改变视野

前言

Stream大意概括 将一个列表(List)中的所有类铺平转换成一条流水线,按要求将流水线上的所有类一个一个地处理。像极了SQL语句

本篇文章将用通俗易懂的语言为你讲解流操作。如果你有一部分卡住看不懂,跳过去就好,再回去看就会了。

-📚-|需要先了解的知识|-📚-

语言 内容 链接
Java List、ArrayList的使用、基本原理及区别 null
Java Lambda表达式的使用及基本原理 null

-⭐️-|评分|-⭐️-

知识等级 实用性 罕见性
进阶 实用 较少见

原理图

其实整个过程跟流水线差不多。让我们看看由灵魂画手A先生绘制的原理图:

屏幕快照 2019-09-11 上午10.28.23.png

没看懂没关系,做完第一个实践再回来看看。

实践

跳过那些复杂的理论,打开你的IDE,新建一个类名为Arr,把下面的代码复制进去,反复分析代码,最后带着你的疑问再继续:

 1import java.util.ArrayList;
 2import java.util.List;
 3import java.util.stream.Collectors;
 4import java.util.stream.Stream;
 5
 6public class Arr {
 7    public static void main(String[] args) {
 8        //God创建星球
 9        星球 星球1 = new 星球();
10        星球 星球2 = new 星球();
11        星球 星球3 = new 星球();
12        //God给星球起名
13        星球1.设置星球名("地球");
14        星球2.设置星球名("太阳");
15        星球3.设置星球名("唱跳Rap篮球");
16        //God把星球添加到ArrayList中
17        List<星球> 宇宙 = new ArrayList();
18        宇宙.add(星球1);
19        宇宙.add(星球2);
20        宇宙.add(星球3);
21        //灭霸出现
22        Stream<星球> 灭霸 = 宇宙.stream().map(
23                星球 -> {
24                    //如果星球名中带“球”字,则毁灭
25                    if (星球.获取星球名().indexOf("球") != -1) {
26                        星球.设置星球名("已毁灭");
27                    }
28                    return 星球;
29                });
30        //将全部星球重新转换为新宇宙
31        List<星球> 新宇宙 = 灭霸.collect(Collectors.toList());
32        //打印星球存活情况
33        for (星球 i : 新宇宙) {
34            System.out.println(i.获取星球名());
35        }
36    }
37}
38
39class 星球 {
40    private String 星球名;
41
42    public void 设置星球名(String 星球名) {
43        this.星球名 = 星球名;
44    }
45
46    public String 获取星球名() {
47        return 星球名;
48    }
49}
50

map()就是将流中的类挨个儿揪出来,并临时命名为一个局部的星球变量,并且对这个变量进行判断呢修改后,再返回新的星球给灭霸。

运行结果:

1已毁灭
2太阳
3已毁灭

整理思路

⬇️反复运行并分析结果,然后和我一起整理下思路 ⬇️
1 星球是一个类,存储了星球名,并提供了设置与获取星球名的方法;
2 主方法中,我们实例化了3个星球,并将其命名为“地球”、“太阳”、“唱跳Rap篮球”;
3 宇宙是一个列表,而后我们将3个星球添加到了宇宙中;
4 灭霸是实例化的流操作,执行宇宙.stream()后就能得到我们的流;
5 使用流进行了map()操作后,使用灭霸.collect()方法将灭霸中的流重新收集为一个列表,名为新宇宙
6 遍历新宇宙后,我们发现数据已经修改成功。

其中的流化操作,就像是下边这条伪SQL语句:

1UPDATE 宇宙 SET 星球名=IF(... .indexOf("球") != -1 ...);

SQL语义为:将所有宇宙中的星球名更新,其中如果包含“球”的则修改为“已毁灭”,其它不变

那么如果下面这条SQL语句,应该怎么表达?

1SELECT * FROM 宇宙 WHERE LOCATE("球", 星球名) LIMIT 1;

将星球名包含“球”字的星球筛选(即不打印不包含“球”字的星球名),并限制仅打印一个。

修改灭霸部分:

1        Stream<星球> 灭霸 = 宇宙.stream()
2                .filter(星球 -> 星球.获取星球名().indexOf("球") != -1)
3                .limit(1);

运行结果:

1地球

其它流操作

其它的几个流操作:

去重 stream().distinct()
排序 stream().sorted()
扔掉前N个元素 stream().skip(n)

自己尝试下吧!

Stream.of

我们演示使用的List中的.stream()方法是继承自Collection集合类的,所以也就是说,只要是基于Collection的集合,大多数都是支持使用Stream类进行流操作的。

那么如果我想省略掉建立List步骤,直接生成为一个Stream流呢?

1Stream.of(星球1, 星球2, 星球3);

将代码套用到刚刚的实例中。修改主方法:

 1    public static void main(String[] args) {
 2        //God创建星球
 3        星球 星球1 = new 星球();
 4        星球 星球2 = new 星球();
 5        星球 星球3 = new 星球();
 6        //God给星球起名
 7        星球1.设置星球名("地球");
 8        星球2.设置星球名("太阳");
 9        星球3.设置星球名("唱跳Rap篮球");
10        //灭霸出现
11        Stream<星球> 灭霸 = Stream.of(星球1, 星球2, 星球3)
12                .filter(星球 -> 星球.获取星球名().indexOf("球") != -1)
13                .limit(1);
14        //将全部星球重新转换为新宇宙
15        List<星球> 新宇宙 = 灭霸.collect(Collectors.toList());
16        //打印星球存活情况
17        for (星球 i : 新宇宙) {
18            System.out.println(i.获取星球名());
19        }
20    }

是不是优美了一点儿呢?

后语

排坑

如果你将灭霸部分修改为:

1        Stream<星球> 灭霸 = Stream.of(星球1, 星球2, 星球3);
2        灭霸.filter(星球 -> 星球.获取星球名().indexOf("球") != -1)
3                .limit(1);

再次运行,你会发现出现报错:

1Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
2	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:229)
3	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
4	at Arr.main(Arr.java:21)

这是由于每个Stream只能使用一次。将代码稍稍修改:

1        Stream<星球> 灭霸 = Stream.of(星球1, 星球2, 星球3);
2        灭霸 = 灭霸.filter(星球 -> 星球.获取星球名().indexOf("球") != -1)
3                .limit(1);

将返回的新结果复用,这样就不会报错了。