用过Optional;那用过Try么?

本文转载自微信公众号「小姐姐味道」,作者小姐姐养的狗。转载本文请联系小姐姐味道公众号。   

创新互联长期为近1000家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为万山企业提供专业的成都网站建设、成都做网站,万山网站改版等技术服务。拥有10多年丰富建站经验和众多成功案例,为您定制开发。

Java的Optional非常好用。我们一般使用Optional做非空处理,省去if的处理。主要的目的,就是为了解决Java中臭名昭著的空指针异常。

比如我们在平常的编码中,经常遇到对输入参数的非空判断。

 
 
 
 
  1. public void getXXX(Map params) { 
  2.     Map map = params; 
  3.     if (map == params) { 
  4.         map = new HashMap<>(); 
  5.     } 

这种代码一多,我们的程序就会慢慢变成shit mountain。这个时候就可以使用Optional进行改造。

 
 
 
 
  1. public void getXXX(Map params) { 
  2.     Map map = Optional.ofNullable(params).orElse(new HashMap<>()); 

代码行数少了,逻辑清晰,同时自己的绩效也降低了 :)。

1. 复杂例子

看一个比较复杂的例子。

假如我们需要的数据层次比较深。

 
 
 
 
  1. String cityCode = customer.getAddress().getCity().getCityCode().substring(0,3); 

这样获取是不合理的,因为其中的某一环,可能是空,会抛出空指针的。所以,我们需要一层层的进行判断。

 
 
 
 
  1. public void getCityCode(Customer customer) { 
  2.     String cityCode = "000"; 
  3.     if (customer != null) { 
  4.         Address address = customer.getAddress(); 
  5.         if (null != address) { 
  6.             City city = address.getCity(); 
  7.             if (city != null) { 
  8.                 String code = city.getCityCode(); 
  9.                 if (null != code && code.length() >= 3) { 
  10.                     cityCode = code.substring(0, 3); 
  11.                 } 
  12.             } 
  13.         } 
  14.     } 
  15.     System.out.println(cityCode); 

使用Optional的lambda语法,我们可以把代码改成下面这样:

 
 
 
 
  1. public void getCityCode(Customer customer) { 
  2.     String cityCode = Optional.ofNullable(customer) 
  3.             .map(c -> c.getAddress()) 
  4.             .map(a -> a.getCity()) 
  5.             .map(c -> c.getCityCode()) 
  6.             .filter(s -> s.length() >= 3) 
  7.             .map(s -> s.substring(0, 3)) 
  8.             .orElse("000"); 

代码是不是颜值很高?

颜值虽高,下面还是要点一些偏门的重点内容。

2. Optional的隐秘内容

其实,早在Java8发布之前(2014),guava就有了类似的工具,但由于当时并没有lambda语法,所以只能做些简单的应用。

Guava的optional支持序列化,可以在RPC框架方法中返回,但是一般很少用。

Java的Optional却根本无法序列化。为什么java8的Optional没有实现序列化,这里有个讨论,可以看看http://mail.openjdk.java.net/pipermail/jdk8-dev/2013-September/003186.html

另外Java8比Guava多了ifPresent、map、 filter、 flatMap、 orElseThrow这些方法。鉴于现在使用Guava Optional的人越来越少,不提也罢。

Optional会对GC有一定压力,如果开发底层框架,还是慎重使用,netty就曾经过测试,最后放弃了Optional。

但我还是喜欢用。谁让国内大多数都是cruder呢?

3. Try为何物?

长期使用使用Java编码的Javaer,在见了Scala、Kotlin一类的语言后,会有一种惊艳的感觉。但这些包实在是太大了,引入有一定的成本,只能眼巴巴的馋她们的身子。

但是,Java 标准库对函数式编程的 API 支持相对比较有限。有没有一种轻量级的方式,来增强我们的Java库呢?要是能和Lambda表达式结合起来,那就更妙了。Vavr就是这样一个简单的Jar包,让我们的代码,写起来更加流畅。

它的maven坐标是:

 
 
 
 
  1.  
  2.     io.vavr 
  3.     vavr 
  4.     0.10.3 
  5.  

下面是一段伟大的睡眠排序法的代码:

 
 
 
 
  1. public class SleepSort implements Runnable { 
  2.     private int num; 
  3.     public SleepSort(int num) { 
  4.         this.num = num; 
  5.     } 
  6.     @Override 
  7.     public void run() { 
  8.         try { 
  9.             Thread.sleep(num * 10); 
  10.         } catch (Exception e) { 
  11.             e.printStackTrace(); 
  12.         } 
  13.         System.out.print(num + " "); 
  14.     } 
  15.     public static void main(String[] args) { 
  16.         int[] nums = {5, 22, 10, 7, 59, 3, 16, 4, 11, 8, 14, 24, 27, 25, 26, 28, 23, 99}; 
  17.         Arrays.stream(nums).forEach(n->new Thread(new SleepSort(n)).start()); 
  18.     } 

其中的Run部分,太多无用的信息,我们可以使用Try来改造。

我们可以简化为下面两行:

 
 
 
 
  1. Try.run(()->Thread.sleep(num*10)) 
  2.         .andThen(()->System.out.print(num + " ")); 

它支持非常多的方法,可以完成大多数后续的业务处理。比如,在onFailure方法里,加入对异常信息的日志记录。

而常见的jackson json的处理,可以简化成下面的代码:

 
 
 
 
  1. String json = Try.of(() -> objectMapper.writeValueAsString(str)).getOrElse("{}"); 

Try就是这么好用。最重要的是,vavr的大小只有800多kb。

4. vavr的更多操作

vavr支持Tuple(元组)、Option、Try、Either、集合便捷操作、多元函数、柯里化方法(curring)等。

可以看一下vavr版本的if else。下面是四个分支的代码。里面这些奇怪的符号,证明它也只是语法糖。

 
 
 
 
  1. public String vavrMatch(String input) { 
  2.     return Match(input).of( 
  3.             Case($("a"), "a1"), 
  4.             Case($("b"), "b2"), 
  5.             Case($("c"), "c3"), 
  6.             Case($(), "unknown") 
  7.     ); 

再比如,你想要定义一个函数,而不是一个类,在Java中可以使用Function。但可惜的是,Java的Function只支持一个参数。

使用Vavr的Function,最多支持22个参数!

再比如,你想要在一个方法中,返回多个值。这个,在python中很容易实现,在Java中就不得不定义一个Class去接收。

元组,就可以支持多个返回值的组合。比如下面的代码:

 
 
 
 
  1. // (Java, 8) 
  2. Tuple2 java8 = Tuple.of("Java", 8);  
  3.  
  4. // "Java" 
  5. String s = java8._1;  
  6.  
  7. // 8 
  8. Integer i = java8._2;  

vavr支持一次性返回8个值。

另外,还有lazy等小工具。比如延迟获取值。

 
 
 
 
  1. Lazy lazy = Lazy.of(Math::random); 
  2. lazy.isEvaluated(); // = false 
  3. lazy.get();         // = 0.123 (random generated) 
  4. lazy.isEvaluated(); // = true 
  5. lazy.get();         // = 0.123 (memoized) 

这样的扩展方法有很多。但我最常用的,还是Try和元组。它让代码变的更加优雅,表达意图也更加清晰。

哦对了。resilience4j就重度使用了vavr,就是那个Hystrix不再更新之后,官方推荐的那个熔断组件。

作者简介:小姐姐味道 (xjjdog),一个不允许程序员走弯路的公众号。聚焦基础架构和Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不一样的味道。我的个人微信xjjdog0,欢迎添加好友,进一步交流。

文章标题:用过Optional;那用过Try么?
当前URL:http://www.mswzjz.cn/qtweb/news21/229321.html

攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能