vavr:让你像写Scala一样写Java
本文阅读时间大约7分钟。
Hystrix是Netflix开源的限流、熔断降级组件,去年发现Hystrix已经不再更新了,而在github主页上将我引导到了另一个替代项目——resilience4j,这个项目是基于Java 8开发的,并且只使用了vavr库,也就是我们今天要介绍的主角。
Lambda表达式
既然要谈vavr,那么先要谈为什么要使用vavr,vavr是为了增强Java的函数式编程体验的,那么这里先介绍下Java中的函数式编程。
Java 8引入了函数式编程范式,思路是:将函数作为其他函数的参数传递,其实在Java 8之前,Java也支持类似的功能,但是需要使用接口实现多态,或者使用匿名类实现。不管是接口还是匿名类,都有很多模板代码,因此Java 8引入了Lambda表达式,正式支持函数式编程。
比方说,我们要实现一个比较器来比较两个对象的大小,在Java 8之前,只能使用下面的代码:
Compartor<Apple> byWeight = new Comparator<Apple>() {
public int compare(Apple a1, Apple a2) {
return a1.getWeight().compareTo(a2.getWeight());
}
}
上面的代码使用Lambda表达式可以写成下面这样(IDEA会提示你做代码的简化)
Comparator<Apple> byWeight = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
关于Lambda表达式,你需要掌握的知识点有:
Lambda表达式可以理解为是一种匿名函数:它没有名称,但是又参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表;
函数式接口就是仅仅声明了一个抽象方法的接口;
@FunctionalInterface注解对于函数式接口的作用,类似于@Override对于被重写的方法——不是必须的,但是用了有助于提升代码的可读性,因此如果你在开发中自己定义函数式接口,最好也使用这个注解修饰;
Java 8自带一些常用的函数式接口,放在
java.util.function包里,包括Predicate、Function<T,R>、Supplier、Consumer和BinaryOperator等等;
vavr
受限于 Java 标准库的通用性要求和二进制文件大小,Java 标准库对函数式编程的 API 支持相对比较有限。函数的声明只提供了 Function 和 BiFunction 两种,流上所支持的操作的数量也较少。基于这些原因,你也许需要vavr 来帮助你更好得使用Java 8进行函数式开发。
如下图所示,vavr提供了不可变的集合框架;更好的函数式编程特性;元组。vavr是在尝试让Java拥有跟Scala类似的语法。
集合
Vavr实现了一套新的Java集合框架来匹配函数式编程范式,vavr提供的集合都是不可变的。在Java中使用Stream,需要显示得将集合转成steam的步骤,而在vavr中则免去了这样的步骤。
vavr的List是不可变的链表,在该链表对象上的操作都会生成一个新的链表对象。使用Java 8的代码:
Arrays.asList(1, 2, 3).stream().reduce((i, j) -> i + j);
IntStream.of(1, 2, 3).sum();
使用vavr实现相同的功能,则更加直接:
//io.vavr.collection.List
List.of(1, 2, 3).sum();
vavr的Stream是惰性链表,元素只有在必要的时候才会参与计算,因此大部分操作都可以在常量时间内完成。
函数(Functions)
Java 8提供了接受一个参数的函数式接口Function和接受两个参数的函数式接口BiFunction,vavr则提供了最多可以接受8个参数的函数式接口:Function0、Function1、Function2、Function3、Function4……Function8。
vavr还提供了更多函数式编程的特性:
组合(Composition)。在数学上,函数组合可以用两个函数形成第三个函数,例如函数f:X->Y和函数g:Y->Z可以组合成h:g(f(x)),表示X->Z。这里看个组合的例子
Lifting。你是不是常常写这种代码:调用一个函数,判断它的返回值是否符合需求,或者需要catch所有异常以防异常情况,甚至是catch(Throwable t)。Lifting特性就是为了解决这个问题而存在的,可以在内部处理异常情况,并将异常转换成一个特殊的结果None,这样函数外部就可以用统一的模式去处理函数结果。举个例子:
柯里化方法(Curring) 柯里化(Currying)指的是将原来接受多个参数的函数变成新的接受一个参数的函数的过程。对于Java来说,这是提供默认值的一种方式,这里看个例子
方法缓存(Memorization) 这是一种缓存,某个方法只需要执行一次,后面都会返回第一次的结果;但是在实际应用中用到的地方应该不多。
模式匹配
模式匹配是函数式编程语言中的概念,目前Java中还不支持这个特性,使用vavr可以用Java写模式匹配的代码。Java中的switch...case语句只能针对常量起作用,而使用模式匹配则可以对另一个函数的返回结果起作用,功能非常抢到。下面的例子分别给出了使用if、switch...case、模式匹配三个语法实现同样功能的例子,可以看出,模式匹配有助于减少代码行数。
参考资料
《Java 8实战》
https://github.com/resilience4j/resilience4j
https://www.baeldung.com/vavr
https://www.vavr.io/vavr-docs/
下方查看历史文章
025:为什么需要将Logger对象声明为private static final类型的
024:Java流实现Shell:cat 1.log | grep a | sort | uniq -c | sort -rn
本号专注于后端技术、JVM问题排查和优化、Java面试题、个人成长和自我管理等主题,为读者提供一线开发者的工作和成长经验,期待你能在这里有所收获。
在看点这里
vavr:让你像写Scala一样写Java的更多相关文章
- IDEA写scala简单操作
今天尝试了一下在IntelliJ IDEA里面写Scala代码,并且做到和Java代码相互调用,折腾了一下把过程记录下来. 首先需要给IntelliJ IDEA安装一下Scala的插件,在IDEA的启 ...
- JAVA语言之怎样写出高性能的Java代码?
本文主要向大家介绍了JAVA语言之怎样写出高性能的 Java 代码?通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. 在这篇文章中,我们将讨论几个有助于提升Java应用程序性能的方法.我 ...
- java能不能自己写一个类叫java.lang.System/String正确答案
原文: http://www.wfuyu.com/php/22254.html 未做测试 ! 最近学习了下java类加载相干的知识.然后看到网上有1道面试题是 能不能自己写个类叫java.lang.S ...
- 象写程序一样写博客:搭建基于github的博客
象写程序一样写博客:搭建基于github的博客 前言 github 真是无所不能.其 Pages 功能 支持上传 html,并且在页面中显示.于是有好事者做了一个基于 github 的博客管理工具 ...
- 请阐述调用Activity有哪几种方法,并写出相关的Java代码
请阐述调用Activity有哪几种方法,并写出相关的Java代码. 答案:可以采用两种方式调用Activity:显示调用和隐式调用.显示调用直接指定了Activity,代码如下: Intent int ...
- 《自己动手写CPU》写书评获赠书活动结果
<自己动手写CPU>写书评获赠图书的读者有: 京东:8***2.16号哨兵.magicyu.kk6803.jddickyd.杰出的胡兵 亚马逊:徐贺.马先童.jaychen.farmfar ...
- 手写代码注意点--java.lang.Math 相关
1-如果用到了Math的函数,需要手动写上: import java.lang.Math; 2-求x的y次方,用的是Math.pow(x,y); 注意,返回值是double!!! 不是int, 如果需 ...
- 如何写出健壮的Java代码
近来在公司写代码,写出的代码发现BUG很多,为了实现一个功能,代码改了又改,影响了工单的效率,也影响个人绩效,因此从网上找了些关于写健壮代码的文章看了看,再加上自己的一些经验总结. 所谓健壮的代码是指 ...
- SSD 为什么顺序写比随机写性能更好?
SSD以Page为单位做读写,以Block为单位做垃圾回收,Page一般有16KB大小,Block一般有几十MB大小,SSD写数据的逻辑是: 1)将该块数据所在的Page读出 2)修改该Page中该块 ...
随机推荐
- 原始js---JavaScript注册用正则验证用户名密码手机号邮箱验证码
注册文件 reg.html <html><style> #btn{ background-color: red; color:white; width: 235px; } sp ...
- 【JZOJ5739】【20190706】毒奶
题目 有\(n\)个现实城市,另有\(n\)个幻想城市 原图中在现实城市存在\(m\)条边,在幻想城市存在\(m-1-n\)条边 一个排列是合法的当且进当显示城市 \(i\) 向幻想城市 \(p_i\ ...
- 使用jackson转换xml格式数据进行响应
最近在做微信扫码支付的功能,按照微信开发文档与支付平台进行数据交互只能使用XML格式的数据,调用别人定义的接口就需要按规则来嘛,没办法.自己之前使用jackson,主要是因为SpringMVC默认将j ...
- NIO (一) NIO是什么
参考文档:java为什么需要NIO:https://liuchi.coding.me/2017/08/01/浅谈Java为什么需要NIO/美团技术团队 NIO浅析:https://tech.meitu ...
- 关于Echarts柱状图实现的细节
echarts柱状图显示数值[1] echarts2: itemStyle : { normal: {label : {show: true, position: 'top'}}}, echarts ...
- Java四则运算——图形化界面
一.前提 (1)作业来源:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/2213 (2)GitHub地址:https://github ...
- 《Linux就该这么学》培训笔记_ch13_使用Bind提供域名解析服务
<Linux就该这么学>培训笔记_ch13_使用Bind提供域名解析服务 文章最后会post上书本的笔记照片. 文章主要内容: DNS域名解析服务 安装并部署Bind服务程序 部署从服务器 ...
- 【Python + Selenium3】自动化测试之DDT数据驱动并生成测试报告以及用yagmail邮件发送文件
我的文件路径 一.DDT代码: import unittest from time import sleep from selenium import webdriver from ddt impor ...
- Scrum story
鸡和猪的故事故事: 一天,一只鸡散步时遇见了猪. 鸡对猪说:“嗨,我们合伙开个餐厅吧.” 猪说:“好啊,那准备取什么店名呢?” 鸡说:“要不,就叫火腿和鸡蛋吧.” 猪直接拒绝了:“那可不行.我要割肉, ...
- Delphi阿里云邮件推送【支持单一发信、邮件批量发送和获取指定条件下的发送数据】
作者QQ:(648437169) 点击下载➨Delphi阿里云邮件推送 阿里云api文档 [Delphi阿里云邮件推送]支持SingleSendMail(单一发信接口). ...