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

推荐订阅源

Google DeepMind News
Google DeepMind News
S
Secure Thoughts
Application and Cybersecurity Blog
Application and Cybersecurity Blog
AWS News Blog
AWS News Blog
GbyAI
GbyAI
腾讯CDC
WordPress大学
WordPress大学
V
V2EX
小众软件
小众软件
C
CXSECURITY Database RSS Feed - CXSecurity.com
M
MIT News - Artificial intelligence
T
Troy Hunt's Blog
H
Hacker News: Front Page
Scott Helme
Scott Helme
The Hacker News
The Hacker News
Schneier on Security
Schneier on Security
K
Kaspersky official blog
S
Security @ Cisco Blogs
N
News | PayPal Newsroom
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
Threatpost
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Martin Fowler
Martin Fowler
P
Privacy International News Feed
Blog — PlanetScale
Blog — PlanetScale
D
DataBreaches.Net
O
OpenAI News
P
Proofpoint News Feed
J
Java Code Geeks
B
Blog RSS Feed
Attack and Defense Labs
Attack and Defense Labs
L
Lohrmann on Cybersecurity
T
Threat Research - Cisco Blogs
C
Cybersecurity and Infrastructure Security Agency CISA
阮一峰的网络日志
阮一峰的网络日志
P
Palo Alto Networks Blog
Engineering at Meta
Engineering at Meta
AI
AI
Google DeepMind News
Google DeepMind News
雷峰网
雷峰网
Microsoft Azure Blog
Microsoft Azure Blog
Simon Willison's Weblog
Simon Willison's Weblog
人人都是产品经理
人人都是产品经理
T
Tailwind CSS Blog
G
GRAHAM CLULEY
A
Arctic Wolf
N
Netflix TechBlog - Medium
L
LINUX DO - 最新话题
爱范儿
爱范儿
博客园 - 聂微东

技术改变视野

为程序员、设计师打造的摸鱼社区:摸鱼派! - 技术改变视野 大白话 | 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);

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