正如我之前所写的,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)作为返回集合。

ava 8中的新功能特性的更多相关文章

  1. Android P新功能特性抢先看

    2018年3月8日,Google推出了Android P Preview版本,并提供官方镜像下载. 为了让广大开发者能够及时了解Android P的新功能特性,提前为您的app进行良好适配,WeTes ...

  2. Windows 10 版本 1507 中的新 AppLocker 功能

    要查看 Windows 10 版本信息,使用[运行]> dxdiag  回车 下表包含 Windows 10 的初始版本(版本 1507)中包括的一些新的和更新的功能以及对版本 1511 的 W ...

  3. SQL语句 在一个表中插入新字段

    SQL语句 在一个表中插入新字段: alter table 表名 add 字段名 字段类型 例: alter table OpenCourses add Audio varchar(50)alter ...

  4. Myeclipse中导入新项目报叹号

    Myeclipse中导入新项目报红色叹号 原因是导入项目中,有的jar路径不对, 在上图中,先把报错的jar移除,之后将JRE开头的那个library移除,最后点击add Library,选择jre. ...

  5. HTML5 中的新属性autocomplete="off"失效的解决方法(兼容firefox,IE,360)

    因为业务需求,在写一个注册页面的时候,发现浏览器会自动填充此域名下已经保存的账号密码,给用户带来不便.加了HTML5 中的新属性autocomplete="off" ,但是并没有产 ...

  6. SQLSERVER2014中的新功能

    SQLSERVER2014中的新功能 转载自:http://blog.csdn.net/maco_wang/article/details/22701087 博客人物:maco_wang SQLSER ...

  7. ASP.NET 5与MVC 6中的新特性

    差点忘了提一句,MVC 6中默认的渲染引擎Razor也将得到更新,以支持C# 6中的新语法.而Razor中的新特性还不只这一点. 在某些情况下,直接在Web页面中嵌入某些JSON数据的方式可能比向服务 ...

  8. 在ECSHOP后台左侧导航中增加新菜单

    在ECSHOP后台左侧导航中增加新菜单 ECSHOP教程/ ecshop教程网(www.ecshop119.com) 2011-11-08   有个别高级用户(懂PHP的),提到这样的问题: 在后台管 ...

  9. 向CDH5集群中添加新的主机节点

    向CDH5集群中添加新的主机节点 步骤一:首先得在新的主机环境中安装JDK,关闭防火墙.修改selinux.NTP时钟与主机同步.修改hosts.与主机配置ssh免密码登录.保证安装好了perl和py ...

随机推荐

  1. Intel支持八九代酷睿的B365芯片组将登场亮相

    不久前,Intel悄然推出了新款芯片组B365,看起来像是B360的升级版,但事实上二者并无太大关系. 根据最新曝料,基于B365芯片组的主板将在1月16日登场亮相,支持八九代酷睿. 同时获悉,B36 ...

  2. PAT A1110 Complete Binary Tree (25 分)——完全二叉树,字符串转数字

    Given a tree, you are supposed to tell if it is a complete binary tree. Input Specification: Each in ...

  3. PAT A1126 Eulerian Path (25 分)——连通图,入度

    In graph theory, an Eulerian path is a path in a graph which visits every edge exactly once. Similar ...

  4. AliOS-Things Visual studio code helloworld 入门

    配置环境的时候别忘了下载:GCC工具链:https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads AliOS Thing ...

  5. 【Codeforces Round 1110】Codeforces Global Round 1

    Codeforces Round 1110 这场比赛只做了\(A\).\(B\).\(C\),排名\(905\),不好. 主要的问题在\(D\)题上,有\(505\)人做出,但我没做出来. 考虑的时候 ...

  6. 动手动脑(lesson 6)

    一.继承条件下的构造方法调用 运行结果: 二. 答:构造函数的主要作用是初始化环境,子类是继承的父类,也就是说父类中有的子类全都有,而子类中有的父类不一定有,因此子类运行会调用父类构造函数,而父类不可 ...

  7. 命名 PRIMARY KEY 约束

    1.注释:如果您使用 ALTER TABLE 语句添加主键,必须把主键列声明为不包含 NULL 值(在表首次创建时). mysql> ALTER TABLE appcc_user  ADD CO ...

  8. Maven私有仓库: 发布release版本报错:Return code is: 400, ReasonPhrase: Repository does not allow upd ating assets: maven-releases.

    今天在将一个maven组件由SNAPSHORT升级为正式版本1.0.0,然后执行发布: mvn clean deploy -pl ielong-common -am -DskipTests, 报错:R ...

  9. [Oracle]数据库的Control File 取Dump后的样例

    [Oracle]数据库的Control File 取Dump后的样例: 片段截取-------------------------------(size = 40, compat size = 40, ...

  10. ActiveMQ在C#中的应用

    本文是在.NET Framework框架下的应用,截止到目前ActiveMQ还不支持.NET Core,而RabbitMQ已经支持.NET Core,希望ActiveMQ能尽快支持. ActiveMQ ...