本文由 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:不要再用循环了的更多相关文章

  1. Java编程基础-选择和循环语句

    一.选择结构语句 选择结构:也被称为分支结构.选择结构有特定的语法规则,代码要执行具体的逻辑运算进行判断,逻辑运算的结果有两个,所以产生选择,按照不同的选择执行不同的代码. Java语言提供了两种选择 ...

  2. Java使用条件语句和循环结构确定控制流

    与任何程序设计语言一样,Java使用条件语句和循环结构确定控制流.本文将简单讲解条件.循环和switch. 一.块作用域 块(block),即复合语句.是指由一对大括号括起来的若干条简单的Java语句 ...

  3. Java-Runoob-高级教程-实例-方法:13. Java 实例 – for 和 foreach循环使用

    ylbtech-Java-Runoob-高级教程-实例-方法:13. Java 实例 – for 和 foreach循环使用 1.返回顶部 1. Java 实例 - for 和 foreach循环使用 ...

  4. 最近准备把安卓和java的知识再回顾一遍,顺便会写博客上!千变万化还都是源于基础,打扎实基础

    最近准备把安卓和java的知识再回顾一遍,顺便会写博客上!千变万化还都是源于基础,打扎实基础,加油吧 距离去北京还有23天

  5. Java学习笔记八:Java的流程控制语句之循环语句

    Java的流程控制语句之循环语句 一:Java循环语句之while: 生活中,有些时候为了完成任务,需要重复的进行某些动作.如参加 10000 米长跑,需要绕 400 米的赛道反复的跑 25 圈.在 ...

  6. 当然,perl等脚本服务器是一般默认安装了,你入侵了一台主机,总不能先装配 Java 环境然后再开干吧?

    转自:https://www.zhihu.com/question/20173592 当然,perl等脚本服务器是一般默认安装了,你入侵了一台主机,总不能先装配 Java 环境然后再开干吧?

  7. Java数组使用以及foreach循环

    Java数组使用以及foreach循环 二话不说,先甩一个简单的程序: final int NUM= 10; int[] arrays = new int[NUM]; System.out.print ...

  8. Java继承之再谈构造器

    目录 Java继承之再谈构造器 初始化基类 默认构造器 带参数的构造器 子类调用父类构造器 Java继承之再谈构造器 初始化基类 前面提到,继承是子类对父类的拓展.<Thinking in Ja ...

  9. 再谈循环&迭代&回溯&递归&递推这些基本概念

    循环:不断重复进行某一运算.操作. 迭代:不断对前一旧值运算得到新值直到达到精度.一般用于得到近似目标值,反复循环同一运算式(函数),并且总是把前一 次运算结果反代会运算式进行下一次运算 递推:从初值 ...

  10. Java入门 - 语言基础 - 09.循环结构

    原文地址:http://www.work100.net/training/java-loop.html 更多教程:光束云 - 免费课程 循环结构 序号 文内章节 视频 1 概述 2 while循环 3 ...

随机推荐

  1. Git 基本使用配置

    // 1.配置用户名邮箱:用于记录你个人的用户名称和电子邮件地址,用户名可随意修改,git 用于记录是谁提交了更新,以及更新人的联系方式: $ git config --global user.nam ...

  2. 弹出对话框 UIAlertController

    双选 //实例化UIAlertController var av=UIAlertController(title: "

  3. 发现一款移动web端远程调试工具weinre , 哈哈!

    之前调试一直用的是chrome的远程调试,虽然效果很不错,但是在调试cordova,微信时多有不便. 在git上找工具时发现了这个:weinre,使用方法非常简单 附上git地址: https://g ...

  4. js 中的流程控制—while和do while

    while语句: while(exp){  }如果为true ,执行代码块里的语句,如果为false,跳出循环 <script> var i =1 ; while (i<10){ / ...

  5. Servlet 是否线程安全 看完便知

    Servlet 是否线程安全 看完便知 转自:http://blog.sina.com.cn/s/blog_6448959f0100kct7.html     摘 要:介绍了Servlet多线程机制, ...

  6. LightOj_1265 Island of Survival

    题目链接 题意: 在孤岛生存, 孤岛上有t头老虎,d头鹿, 每天会出现随机出现两只生物(包括你自己), 如果出现了一只老虎,那么你将被吃掉, 如果两只老虎, 则两只老虎会同归于尽,其他情况你都将生存下 ...

  7. Tomcat根目录下work文件夹的作用

    今天遇到了这样的一个问题:就是我之前把项目部署到了tomcat下,运行没有任何问题,后来我把我之前的改项目的原项目文件部署上去后,运行时总是出现之前的界面,而服务器又是启动正常的;通过仔细的检查后,发 ...

  8. Immutable Object模式

    多线程共享变量的情况下,为了保证数据一致性,往往需要对这些变量的访问进行加锁.而锁本身又会带来一些问题和开销.Immutable Object模式使得我们可以在不使用锁的情况下,既保证共享变量访问的线 ...

  9. Android 隐式意图 让用户选择一个浏览器访问网址

    Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.setData(Uri.parse("h ...

  10. 使用php对多维维数组排序。

    要多php的多维数组排序,可以使用php里的内置函数:array_multisort(); 语法:array_multisort(array1,sorting order,sorting type,a ...