本文由 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

转载自连接:http://www.importnew.com/14841.html

Java 8:用Stream来循环集合的更多相关文章

  1. java 数据类型:Stream流 对象转换为集合collect(Collectors.toList()) ;常用方法count,limit,skip,concat,max,min

    集合对象.stream() 获取流对象,对元素批处理(不改变原集合) 集合元素循环除了用for循环取出,还有更优雅的方式.forEach 示例List集合获取Stream对象进行元素批处理 impor ...

  2. JAVA 8 主要新特性 ----------------(六)集合Stream API

    一.简介Stream Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一 个则是 Stream API(java.util.stream.*).Stream 是 Java8 中处 ...

  3. java通过Stream对list集合分组

    java通过Stream对list集合分组 现在有一个List集合,想对该集合中的数据分组处理,想到java8中的stream,就搞来试试,非常给力!例子如下 1 2 3 4 5 6 7 8 9 10 ...

  4. Android java程序员必备技能,集合与数组中遍历元素,增强for循环的使用详解及代码

    Android java程序员必备技能,集合与数组中遍历元素, 增强for循环的使用详解及代码 作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 For ...

  5. Java 8 特性 —— Stream

    Stream 是用函数式编程方式在集合类上进行复杂操作的工具,其集成了Java 8 中的众多新特性之一的聚合操作,开发者可以更容易地使用Lambda表达式,并且更方便地实现对集合的查找.遍历.过滤以及 ...

  6. Java高级特性 第1节 集合框架和泛型

    Java中,存储多个同类型的数据,可以用数组来实现,但数组有一些缺陷: 数组长度固定不变,布恩那个很好的适应元素数量动态变化的情况 可以通过数组.length获取数组长度,却无法直接获取数组中实际存储 ...

  7. 无情的Java 8 之 Stream和lambda表达式篇

    不好意思,最近刷小视频刷的有点上头 看到这图就不自觉的要来一句:"卧槽,无情" 好了,我要开始正经了 JAVA 8 已经推出有一段时间了, 相比之前, 我们操作集合的方式应该是这样 ...

  8. java中的Stream流

    java中的Stream流 说到Stream便容易想到I/O Stream,而实际上,谁规定"流"就一定是"IO流"呢?在Java 8中,得益于Lambda所带 ...

  9. JAVA中简单的for循环竟有这么多坑,你踩过吗

    JAVA中简单的for循环竟有这么多坑,你踩过吗 实际的业务项目开发中,大家应该对从给定的list中剔除不满足条件的元素这个操作不陌生吧? 很多同学可以立刻想出很多种实现的方式,但你想到的这些实现方式 ...

随机推荐

  1. LVS、Nginx及HAProxy

    本文转载自 linkedkeeper.com   当前大多数的互联网系统都使用了服务器集群技术,集群是将相同服务部署在多台服务器上构成一个集群整体对外提供服务,这些集群可以是 Web 应用服务器集群, ...

  2. Vue中全局过滤器期与局部过滤器期的使用

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. Python 第一个程序

    第一个程序 打开pycharm,新建一个工程,新建一个文件(后缀为.py) 书写最简单的代码:print(人生苦短,我用python!) 执行python代码 使用pycharm的运行按钮 终端下输入 ...

  4. HTML 5的革新之一:语义化标签一节元素标签。

    摘至于:<HTML 5的革新——语义化标签(一)> HTML 5的革新之一:语义化标签一节元素标签. 在HTML 5出来之前,我们用div来表示页面章节,但是这些div都没有实际意义.(即 ...

  5. LeetCode——全排列

    给定一个没有重复数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3]输出:[  [1,2,3],  [1,3,2],  [2,1,3],  [2,3,1],  [3,1,2],  [3 ...

  6. 使用redislive监控redis

    redis监控工具redislive的安装 1. pip安装 如果主机没有pip先安装pip工具 wget --no-check-certificate https://github.com/pypa ...

  7. linux下sendmail邮件系统安装详情

    介绍 sendmail是linux系统中一个邮箱系统,如果我们在系统中配置好sendmail就可以直接使用它来发送邮箱.sendmail的配置文件/etc/mail/sendmail.cf       ...

  8. date( ) 日期函数

    date('Y-m-dT2:00')    实际时间为14:00 date('Y-m-d 2:00')     实际时间为2:00 扩展:每天的时间戳秒数为 86400

  9. zk和eureka的区别(CAP原则)

    作为服务注册中心,Eureka比Zookeeper好在哪里 著名的CAP理论指出,一个分布式系统不可能同时满足C(一致性).A(可用性)和P(分区容错性).由于分区容错性在是分布式系统中必须要保证的, ...

  10. 标准C语言(6)

    数组名称不可以代表任何存储区(数组名称不可以被赋值),数组名称可以代表数组里第一个存储区的地址 /* * 数组练习 * */ #include <stdio.h> #include < ...