Java 8:不要再用循环了
本文由 ImportNew - 进林 翻译自 deadcoderising。欢迎加入翻译小组。转载请见文末要求。
正如我之前所写的,Java 8中的新功能特性改变了游戏规则。对Java开发者来说这是一个全新的世界,并且是时候去适应它了。
在这篇文章里,我们将会去了解传统循环的一些替代方案。在Java 8的新功能特性中,最棒的特性就是允许我们去表达我们想要完成什么而不是要怎样做。这正是循环的不足之处。要确保循环的灵活性是需要付出代价的。return、break 或者 continue都会显著地改变循环的实际表现。这迫使我们不仅要清楚我们要实现怎样的代码,还要了解循环是怎样工作的。
在介绍Java 8的流(Stream)时,我们学会了一些集合操作的实用技巧。现在我们要看看怎样把这些循环转换为更简洁,可读性更高的代码。

开始编码!
好吧,讲的够多了,是时候展示一些例子了!
这次我们要以文章为例子。一篇文章拥有一个标题,一个作者和几个标签。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
private class Article { private final String title; private final String author; private final List<String> tags; private Article(String title, String author, List<String> tags) { this.title = title; this.author = author; this.tags = tags; } public String getTitle() { return title; } public String getAuthor() { return author; } public List<String> getTags() { return tags; } } |
每个例子都会包含一个使用传统循环的方案和一个使用Java 8新特性的方案。
在第一个例子里,我们要在集合中查找包含“Java”标签的第一篇文章。
看一下使用for循环的解决方案。
|
1
2
3
4
5
6
7
8
9
10
|
public Article getFirstJavaArticle() { for (Article article : articles) { if (article.getTags().contains("Java")) { return article; } } return null;} |
现在我们使用Stream API的相关操作来解决这个问题。
|
1
2
3
4
5
|
public Optional<Article> getFirstJavaArticle() { return articles.stream() .filter(article -> article.getTags().contains("Java")) .findFirst(); } |
是不是很酷?我们首先使用 filter 操作去找到所有包含Java标签的文章,然后使用 findFirst() 操作去获取第一次出现的文章。因为Stream是“延迟计算”(lazy)的并且filter返回一个流对象,所以这个方法仅在找到第一个匹配元素时才会处理元素。
现在,让我们获取所有匹配的元素而不是仅获取第一个。
首先使用for循环方案。
|
1
2
3
4
5
6
7
8
9
10
11
12
|
public List<Article> getAllJavaArticles() { List<Article> result = new ArrayList<>(); for (Article article : articles) { if (article.getTags().contains("Java")) { result.add(article); } } return result;} |
使用Stream操作的方案。
|
1
2
3
4
5
|
public List<Article> getAllJavaArticles() { return articles.stream() .filter(article -> article.getTags().contains("Java")) .collect(Collectors.toList()); } |
在这个例子里我们使用 collection 操作在返回流上执行少量代码而不是手动声明一个集合并显式地添加匹配的文章到集合里。
到目前为止还不错。是时候举一些突出Stream API强大的例子了。
根据作者来把所有的文章分组。
照旧,我们使用循环方案。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public Map<String, List<Article>> groupByAuthor() { Map<String, List<Article>> result = new HashMap<>(); for (Article article : articles) { if (result.containsKey(article.getAuthor())) { result.get(article.getAuthor()).add(article); } else { ArrayList<Article> articles = new ArrayList<>(); articles.add(article); result.put(article.getAuthor(), articles); } } return result;} |
我们能否找到一个使用流操作的简洁方案来解决这个问题?
|
1
2
3
4
|
public Map<String, List<Article>> groupByAuthor() { return articles.stream() .collect(Collectors.groupingBy(Article::getAuthor));} |
很好!使用 groupingBy 操作和 getAuthor 方法,我们得到了更简洁、可读性更高的代码。
现在,我们查找集合中所有不同的标签。
我们从使用循环的例子开始。
|
1
2
3
4
5
6
7
8
9
10
|
public Set<String> getDistinctTags() { Set<String> result = new HashSet<>(); for (Article article : articles) { result.addAll(article.getTags()); } return result;} |
好,我们来看看如何使用Stream操作来解决这个问题。
|
1
2
3
4
5
|
public Set<String> getDistinctTags() { return articles.stream() .flatMap(article -> article.getTags().stream()) .collect(Collectors.toSet());} |
棒极了!flatmap 帮我把标签列表转为一个返回流,然后我们使用 collect 去创建一个集合作为返回值。
一切皆有可能
以上的就是如何使用可读性更高的代码代替循环的例子。务必仔细看看Stream API,因为这篇文章仅仅提到它的一些皮毛而已。
更新
收到solarfuse和dhruvgairola的评论后,更新了getDistinctTags()例子,使用集合(Set)作为返回集合。
原文链接: deadcoderising 翻译: ImportNew.com- 进林
译文链接: http://www.importnew.com/14841.html
Java 8:不要再用循环了的更多相关文章
- Java编程基础-选择和循环语句
一.选择结构语句 选择结构:也被称为分支结构.选择结构有特定的语法规则,代码要执行具体的逻辑运算进行判断,逻辑运算的结果有两个,所以产生选择,按照不同的选择执行不同的代码. Java语言提供了两种选择 ...
- Java使用条件语句和循环结构确定控制流
与任何程序设计语言一样,Java使用条件语句和循环结构确定控制流.本文将简单讲解条件.循环和switch. 一.块作用域 块(block),即复合语句.是指由一对大括号括起来的若干条简单的Java语句 ...
- Java-Runoob-高级教程-实例-方法:13. Java 实例 – for 和 foreach循环使用
ylbtech-Java-Runoob-高级教程-实例-方法:13. Java 实例 – for 和 foreach循环使用 1.返回顶部 1. Java 实例 - for 和 foreach循环使用 ...
- 最近准备把安卓和java的知识再回顾一遍,顺便会写博客上!千变万化还都是源于基础,打扎实基础
最近准备把安卓和java的知识再回顾一遍,顺便会写博客上!千变万化还都是源于基础,打扎实基础,加油吧 距离去北京还有23天
- Java学习笔记八:Java的流程控制语句之循环语句
Java的流程控制语句之循环语句 一:Java循环语句之while: 生活中,有些时候为了完成任务,需要重复的进行某些动作.如参加 10000 米长跑,需要绕 400 米的赛道反复的跑 25 圈.在 ...
- 当然,perl等脚本服务器是一般默认安装了,你入侵了一台主机,总不能先装配 Java 环境然后再开干吧?
转自:https://www.zhihu.com/question/20173592 当然,perl等脚本服务器是一般默认安装了,你入侵了一台主机,总不能先装配 Java 环境然后再开干吧?
- Java数组使用以及foreach循环
Java数组使用以及foreach循环 二话不说,先甩一个简单的程序: final int NUM= 10; int[] arrays = new int[NUM]; System.out.print ...
- Java继承之再谈构造器
目录 Java继承之再谈构造器 初始化基类 默认构造器 带参数的构造器 子类调用父类构造器 Java继承之再谈构造器 初始化基类 前面提到,继承是子类对父类的拓展.<Thinking in Ja ...
- 再谈循环&迭代&回溯&递归&递推这些基本概念
循环:不断重复进行某一运算.操作. 迭代:不断对前一旧值运算得到新值直到达到精度.一般用于得到近似目标值,反复循环同一运算式(函数),并且总是把前一 次运算结果反代会运算式进行下一次运算 递推:从初值 ...
- Java入门 - 语言基础 - 09.循环结构
原文地址:http://www.work100.net/training/java-loop.html 更多教程:光束云 - 免费课程 循环结构 序号 文内章节 视频 1 概述 2 while循环 3 ...
随机推荐
- 转:探讨android更新UI的几种方法
本文转自:http://www.cnblogs.com/wenjiang/p/3180324.html 作为IT新手,总以为只要有时间,有精力,什么东西都能做出来.这种念头我也有过,但很快就熄灭了,因 ...
- ios专题 - 使用bundle文件管理资源
[原创]http://www.cnblogs.com/luoguoqiang1985 以前,自己写程序,图片等资源放得比较乱.后来,发现有个更好的方法来管理图片等资源文件 --bundle文件. 1) ...
- linux系统 web在线日志分析
线上环境出现问题时,不能像本地环境一样,断点查找问题,只有根据日志分析来定位问题,当然有资深的经验也是可以的,哈哈. 最基本的就是cat命令,可以通过cat filename,来查看文件全部内容, & ...
- Windows phone 之Interaction.Triggers的使用
两个步骤:1.添加以下两个程序集System.Windows.InteractivityMicrosoft.Expression.Interactions 2.添加xmlns:i="clr- ...
- 新增的output元素 progress元素 meter元素 keygen元素
结果图 <output>是双标签 name:定义对象的唯一属性 for:定义输出域相关的一个或多个元素. form:定义所属的一个至多个表单. progress和meter一般和JS一起使 ...
- win8 + ubuntu14.04 安装步骤
一.首先,从硬盘上划分一个空闲分区(推荐最少20G,每个人也可以按照自己的需要自行设定).记住各个分区的容量,方便安装时辨认.并从Ubuntu官方网站上下载Ubuntu 14.04 LTS 光盘镜像. ...
- excel快递单号查询工具以及源码
Function kdcx(kd, orderid) Dim Err, url, kdtime, link, Errcode, Status Select Case kd '此处支持的快递公司很多的 ...
- hierarchyviewer偶然不能使用的解决方法
在DDMS的device中可以看到设备,并显示可以debug的状态,可以看到不显示进程的信息,但是hierarchyviewer也却不显示各个Window. 在控制台的打印信息如下: - hierar ...
- git 创建多个账户ssh
创建一个账户 创建ssh本地秘钥. $ ssh-keygen -t rsa -C "youremail@xxx.com" 一路回车,会在~/.ssh/目录下生成id_rsa和id_ ...
- java的Arrays类的应用
(2012-08-01 14:48:27) 转载▼ 标签: java arrays类 填充 排序 查找 比较数组 分类: java基础 java.util.Arrays类能方便地操作数组,它提供的所有 ...