[译]Java8:循环与函数式编程
Java8函数式编程的加入彻底改变了游戏规则。对Java开发者来说这是一个全新的世界,我们也需要做出相应的改变。
在这篇文章中我们将找寻传统循环代码的可替代方案。Java8的函数式编程特性改变了编程思路,从 “我们怎样去做” 变成了 “我们想做什么” 。这也是传统循环的缺点。当然传统循环更加的灵活,但其灵活性并不能掩盖他的问题。return、break、continue能直接改变循环的执行流程,强迫我们不仅要理解业务逻辑,同时也要了解循环是怎样工作的。
Java8通过引入stream指令,我们可以在集合上使用强大的函数式操作。现在我们来看看怎样将传统循环转变为更简洁,更具有可读性的代码。
这里将会创建一个Article类,他有三个成员变量:title、author、tags:
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;
}
}
每个例子都会包括一个传统循环的解决方案,和Java8函数式编程的解决方案。
在第一个例子里面,将会在Article集合中寻找tag包含"Java"的第一个对象:
传统循环的解决方案:
public Article getFirstJavaArticle(){
for(Article article : articles){
if(article.getTags().contains("Java")){
return article;
}
}
return null;
}
Java8的解决方案:
public Optional<String> getFirstJavaArticle(){
return articles.stream().filter(article -> article.getTags.contains("Java")).findFirst();
}
首先我们使用filter操作找到所有符合条件的Article,然后调用findFirst()方法得到第一个。因为stream是惰性的而且filter返回了一个stream,因此方法只有在找到第一个匹配时才会去处理这个元素。
现在让我们尝试获取所有匹配的元素。
传统循环解决方案:
public List<Article> getAllJavaArticles() {
List<Article> result = new ArrayList<>();
for (Article article : articles) {
if (article.getTags().contains("Java")) {
result.add(article);
}
}
return result;
}
Java8解决方案:
public List<Article> getAllJavaArticles() {
return articles.stream().filter(article -> article.getTags.contains("Java")).collect(Collectors.toList());
}
在这个例子中我们使用了 collect 方法去筛选stream,而不是自己声明一个集合,并将匹配的参数追加到集合中。
到目前为止都不错,现在是时候来展现 stream api真正的魅力了!
让我们基于author将articles进行分组。
传统循环解决方案:
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);
}
}
}
Java8解决方案:
public Map<String, List<Article>> groupByAuthor() {
return articles.stream().collect(Collectors.groupingBy(Article::getAuthor));
}
通过使用groupingBy操作和getAuthor的方法引用,我们得到了整洁并且可读性高的代码。
现在,让我们在集合中找到Article所有的不重复的tags。
首先时传统循环方案:
public Set<String> getDistinctTags(){
Set<String> result = new HashSet<>();
for(Article article : articles){
result.addAll(article.getTags());
}
return result;
}
Java8解决方案:
public Set<String> getDistinctTags(){
return articles.stream().flatMap(article -> article.getTags().stream()).collect(Collectors.toSet());
}
flatMap帮助我们获取结果流中的tag集合,然后用collect方法创建一个Set并返回结果。
函数式编程拥有无限的可能,这四个例子的目的是怎样将循环替换成更可读的代码。你应该仔细查看stream API,因为相比api这文章仅仅只是皮毛而已。
*英文链接:deadCodeRising
*原创译文
[译]Java8:循环与函数式编程的更多相关文章
- 从java8 说起函数式编程
写在前面 为什么要用函数式编程.看例子: final List<BigDecimal> prices = Arrays.asList( new BigDecimal("10&qu ...
- Java8新特性--函数式编程
在jdk8中什么是函数式接口: 1.被@FunctionalInterface注解修饰的. 2.接口里边只有一个非default的方法. 满足以上2个条件的即为函数式接口,ps:即使一个接口没有被@F ...
- Java8 新特性 —— 函数式编程
本文部分摘录自 On Java 8 概述 通常,传递给方法的数据不同,结果也不同.同样的,如果我们希望方法被调用时的行为不同,该怎么做呢?结论是:只要能将代码传递给方法,那么就可以控制方法的行为. 说 ...
- java8 array、list操作 汇【4】)- Java8 Lambda表达式 函数式编程
int tmp1 = 1; //包围类的成员变量 static int tmp2 = 2; //包围类的静态成员变量 //https://blog.csdn.net/chengwangbaiko/ar ...
- [译]java8新特性:函数式编程(functional programming)的优点
Java8引入了函数式编程,他对java是一个极大的扩展.Java从此不在是一个单纯的面向对象语言,现在他同时混合了函数式编程.这是巨大的改变,需要我们调整面对对象的编程习惯,以适应这些变化. 但是为 ...
- [一] java8 函数式编程入门 什么是函数式编程 函数接口概念 流和收集器基本概念
本文是针对于java8引入函数式编程概念以及stream流相关的一些简单介绍 什么是函数式编程? java程序员第一反应可能会理解成类的成员方法一类的东西 此处并不是这个含义,更接近是数学上的 ...
- 重识Java8函数式编程
前言 最近真的是太忙忙忙忙忙了,很久没有更新文章了.最近工作中看到了几段关于函数式编程的代码,但是有点费解,于是就准备总结一下函数式编程.很多东西很简单,但是如果不总结,可能会被它的各种变体所困扰.接 ...
- JavaScript ES6函数式编程(一):闭包与高阶函数
函数式编程的历史 函数的第一原则是要小,第二原则则是要更小 -- ROBERT C. MARTIN 解释一下上面那句话,就是我们常说的一个函数只做一件事,比如:将字符串首字母和尾字母都改成大写,我们此 ...
- 【JS】394- 简明 JavaScript 函数式编程-入门篇
转载自公众号"程序员成长指北" 写在开头 本文较长,总共分为三大部分:(对于函数式编程以及其优点有一定理解的童鞋,可以直接从 第二部分 开始阅读) 第一部分:首先会通过实际代码介绍 ...
随机推荐
- BZOJ 1010 HNOI2008 玩具装箱 斜率优化
题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=1010 Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的 ...
- ACM做题随做随思
程序停止运行:数组开太大: 输入一串单词,可以“string s; while(cin>>s){//代码块}”,因为cin>>s遇到空格会停止: map<key,valu ...
- c++单例模式代码分析
单例模式就是一个C++语法精华浓缩的一个体现,有句老话:麻雀虽小五脏俱全!来形容单例非常贴切! 下面的代码分析了如果自己malloc并且memcpy一个单例指针会带来很大危害并如何防止这种情况发生. ...
- 编程练习:寻找发帖"水王"
题目: 寻找发帖"水王" 来源: 编程之美 分析 衍生:就是给定一个数组,其中某个元素出现次数超过了数组长度的一半,找出这个元素 方法s 方法1 对这个串进行遍历,同时对出现的元素 ...
- Friends and Enemies(思维)
Friends and Enemies Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Othe ...
- .Net MVC中使用css 和js
@section script { <script language="javascript"> </script> }
- 一道js的前端面试题,主要弄清楚逗号表达式的作用
群里看到的一道前端JS面试题.我以为我会,其实我错了.找了很多资料,写下来. var i,j,k; for( i = 0 , j = 0; i < 10 , j < 6; i++ , j+ ...
- 高中信息技术《算法与程序设计VB(选修)》知识要点
原博主: http://blog.sina.com.cn/buyanshibai [转载] (一)算法 1.定义 相关题解: 1算法:就是解决问题的方法和步骤.算法是程序设计的“灵魂”,算法+数据结构 ...
- 【BZOJ 3551】[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树
这题真刺激...... I.关于Kruskal重构树,我只能开门了,不过补充一下那玩意还是一棵满二叉树.(看一下内容之前请先进门坐一坐) II.原来只是用树上倍增求Lca,但其实树上倍增是一种方法,L ...
- HDU 1059 完全背包
Dividing Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Su ...