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 ...
随机推荐
- 类库探源——System.Delegate
一.MSDN 描述 Delegate 类:表示委托,委托是一种数据结构,它引用静态方法或引用类实例及该类的实例方法.(是不是感觉很像C语言中的函数指针 :) ) 命名空间: System 程序集: ...
- 读书笔记之深入分析Java Web技术内幕
章节: 1 B/SB/S的优点: 客户端使用统一的浏览器(Browser) ,浏览器的统一带来了操作的统一,无论使用什么服务,因为浏览器是相同的,所以操作类似.客户使用简单了.服务端开发简化; 使用统 ...
- 做了五套登录页,晒一下 自己比较满意的~ oh yeh~
- USACO 2.2 Party Lamps 派对灯 (lamps)
题目描述 在IOI98的节日宴会上,我们有N(10<=N<=100)盏彩色灯,他们分别从1到N被标上号码.这些灯都连接到四个按钮: 按钮1:当按下此按钮,将改变所有的灯:本来亮着的灯就熄灭 ...
- Bad owner or permissions on .ssh/config
Bad owner or permissions on $HOME/.ssh/config The ssh with RHEL 4 is a lot more anal about security ...
- Unity NGUI和UGUI与模型、特效的层级关系
目录 1.介绍两大UI插件NGUI和UGUI 2.unity渲染顺序控制方式 3.NGUI的控制 4.UGUI的控制 5.模型深度的控制 6.粒子特效深度控制 7.NGUI与模型和粒子特效穿插层级管理 ...
- 安装ImageMagick扩展出现configure: error: not found. Please provide a path to MagickWand-config or Wand- config program
安装ImageMagick扩展报错: checking ImageMagick MagickWand API configuration program... checking Testing /u ...
- 学渣也要搞 laravel(4)—— 服务 加解密篇
使用 Crypt::encrypt() 对数据进行加密,[注意要引入 use Illuminate\Support\Facades\Crypt;; ] 简单的做个测试: 先分配一个路由: Route: ...
- 树莓派连接GPS模块
一月份的时候觉得好玩买了树莓派,但是太懒没怎么研究,但最近当初买树莓派时的那个梦想又萦绕心头,决定抽空完成一下当年的计划~ GPS模块是其中很重要的一环,于是在某宝上搜索,找了一家相对便宜也很轻巧的G ...
- 横向技术分析C#、C++和Java优劣
转自横向技术分析C#.C++和Java优劣 C#诞生之日起,关于C#与Java之间的论战便此起彼伏,至今不辍.抛却Microsoft与Sun之间的恩怨与口角,客观地从技术上讲,C#与Java都是对传统 ...