[译]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 函数式编程-入门篇
转载自公众号"程序员成长指北" 写在开头 本文较长,总共分为三大部分:(对于函数式编程以及其优点有一定理解的童鞋,可以直接从 第二部分 开始阅读) 第一部分:首先会通过实际代码介绍 ...
随机推荐
- Beat 冲刺 (3/7)
队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 1.界面的修改与完善 展示GitHub当日代码/文档签入记 ...
- bbbbbeta
about beta 写在开头:(小声bb,无任何专业知识) 好了正文开始了 = = beta冲刺对于来说可能是让我觉得非常有成就感的叭,相比于alpha,每天都能写代码的感觉真好鸭(认真脸)(虽然天 ...
- Android问题:could not install *smartsocket* listener;Address already in use
今天启动genymotion后,发现没有ip地址,运行项目时报错: 可见,没有连接到模拟器,无法运行,而先前说过没有ip,自然而然连接不上, 解决放法:将资源管理器打开,将adb全部退出 ...
- java线程(1)——三种创建线程的方式
前言 线程,英文Thread.在java中,创建线程的方式有三种: 1.Thread 2.Runnable 3.Callable 在详细介绍下这几种方式之前,我们先来看下Thread类和Runnabl ...
- password & Encryption
password & Encryption cipher https://dev.tencent.com/login
- C#中的String.Format方法
定义String.Format是将指定的String类型的数据中的每个格式项替换为相应对象的值的文本等效项.(1)string p1="xiaomeng";string p2=&q ...
- BZOJ4651 NOI2016网格(割点)
首先显然可以通过孤立角落里的跳蚤使其不连通,所以只要有解答案就不会大于2.同样显然的一点是当且仅当跳蚤数量<=2且连通时无解.做法其实也很显然了:特判无解,若跳蚤不连通输出0,否则看图中是否无割 ...
- Oracle 同环比排除分母0
A 本期 B 同期(环期) 同比(环比) = (A-B)/B DECODE(NVL(B,0),0,0,ROUND(((A-B)/B),4)), --环比 DECODE(NVL(B),0,0,ROUN ...
- [LeetCode] decode ways 解码方式
A message containing letters fromA-Zis being encoded to numbers using the following mapping: 'A' -&g ...
- 洛谷 P2893 [USACO08FEB]修路Making the Grade 解题报告
P2893 [USACO08FEB]修路Making the Grade 题目描述 A straight dirt road connects two fields on FJ's farm, but ...