业务背景
  首先,业务需求是这样的,从第三方电商平台拉取所有订单,然后保存到公司自己的数据库,需要判断是否有物流信息,如果有物流信息,还需要再进行上传。
  而第三方接口返回的数据是 JSON 格式的,其中物流信息却藏的十分深,如下面所示,JSON 节点是这样的:
基本实现
  因为第三方接口返回的数据是 JSON 格式的,所以需要把 JSON 字符串转换成 Java 对象来进行处理。
 基本实现
  因为第三方接口返回的数据是 JSON 格式的,所以需要把 JSON 字符串转换成 Java 对象来进行处理。
  @JsonIgnoreProperties(ignoreUnknown = true) 
  public class XxxOrder { 
      /** 
       * 物流信息 
       */ 
      @JsonProperty("shippingInfo") 
      private XxxShippingInfo xxxShippingInfo; 
  } 
  上面只是第一层示例,要拿到物流信息,要依次封装四层对象,到真正获取物流信息时要避免空指针,就需要判断四层才能拿到,如示例所示:
  if(xxxOrder != null){ 
      if(xxxOrder.getXxxShippingInfo() != null){ 
          if(xxxOrder.getXxxShippingInfo().getXxxShipmentDetails() != null){ 
              if(xxxOrder.getXxxShippingInfo().getXxxShipmentDetails().getXxxTrackingInfo() != null){ 
                  ... 
              } 
          } 
      } 
  } 
  获取一个物流信息这么麻烦,我也是醉了,这样写也太不优雅了。
  Java 8 实现
  因为我知道 Java 8 可以处理这类的需求,所以我从来没想过用最原始的方式去实现,直接把就用 Java 8 来实现了:
  /** 
  * /private String[] getFulfillments(XxxOrder xxxOrder) {    return Optional.ofNullable(xxxOrder) 
              .map((o) -> o.getXxxShippingInfo())            .map((si) -> si.getXxxShipmentDetails())            .map((sd) -> sd.getXxxTrackingInfo())            .map((t) -> new String[]{t.getTrackingNumber(), t.getTrackingLink()})            .orElse(null);} 
  写完之后,同事居然都直呼看不懂,还特地跑过来问我。
  实现原理
  其实这并没有用什么高超的技术,就是利用 Java 8 Optional 来实现的,细节就不介绍了 ,主要是为了避免空指针而生的,不懂的可以点击这里查看这篇文章
  今天就来介绍下 Optional#map 方法实现这段逻辑的原理,来看下 map 的实现源码:
  public<U> Optional<U> map(Function<? super T, ? extends U> mapper) { 
      // 函数式接口不能为null 
      Objects.requireNonNull(mapper);    // 如果当前没有值,返回一个空的Optional 
      if (!isPresent()) 
          return empty(); 
      else { 
          // 如果当前有值,返回一个函数式处理该值的结果Optional 
          return Optional.ofNullable(mapper.apply(value)); 
      }}// 判断 Optional Value 有没有值 
  public boolean isPresent() {    return value != null; 
  }// 创建一个 Optional,可以为空 
  public static <T> Optional<T> ofNullable(T value) {    return value == null ? empty() : of(value); 
  } 
  所以回到这段程序:
  // 根对象为空就创建一个空Optional,否则就创建一个根对象的Optional 
  Optional.ofNullable(xxxOrder)    // 根对象为空就直接返回空Optional,否则返回这个值的 Optional 
      .map((o) -> o.getXxxShippingInfo()) 
      // 下面依次类推…… 
      .map((si) -> si.getXxxShipmentDetails()) 
      .map((sd) -> sd.getXxxTrackingInfo()) 
      .map((t) -> new String[]{t.getTrackingNumber(), t.getTrackingLink()}) 
      // 取不到值就返回 null 
      .orElse(null); 
  } 
  也许你看完感觉还是看不懂,我承认,确实比较绕,不太好理解,这个只可意会不可言传了,多看多练就理解了。
  这个的关键核心在于,调用 map 时,如果 Optional 没有值就直接返回空的 Optional,而不会调用函数式接口,所以就不会出现空指针。所以只要有一个为空,后面就取不到物流信息。
  程序使用了 .xx.xx.xx 这样的链式调用,调用 map 方法就必须是 Optional,而 map 的返回结果就是 Optional。
  有一个问题是,如果都为空,那不是所有的 map 都会走一遍?在这种情况下会不会影响性能?编译器是否会作优化?这个暂不可知。
  另外还有一个 flatMap 方法,和 map 有什么区别呢?

大神Java8写了一段逻辑,我直呼看不懂的更多相关文章

  1. 我用 Java 8 写了一段逻辑,同事直呼看不懂,你试试看。。

    业务背景 首先,业务需求是这样的,从第三方电商平台拉取所有订单,然后保存到公司自己的数据库,需要判断是否有物流信息,如果有物流信息,还需要再进行上传. 而第三方接口返回的数据是 JSON 格式的,其中 ...

  2. 厉害了,Google大神每天写多少行代码?

    文章转自开源中国社区,编译自:Quora Quora上有个有趣的问题:Google工程师们每天写多少行代码? Google 的 AdMob 全栈工程师 Raymond Farias 在 Quora 发 ...

  3. Unity中的ShaderToys——将大神们写的shader搬到unity中来吧

    http://lib.csdn.net/article/unity3d/38699 这篇文章翻译自国外的一篇文章(这里是原文链接),正在使用unity的你是否在shader toy上发现很多牛逼哄哄的 ...

  4. 今天看了shell大神的写的一个统计脚本

    通过nginx日志统计接口耗时排行 grep '/bigbox?' access_log | awk '{print $7"&process="$NF}'| sed -r ...

  5. SQL 分组排序分页(大神帮写的膜拜一下)

    查询全部: SELECT P3.ID, P3.Name, P3.AddTimeFROM (SELECT Name, MAX(AddTime) AS MaxAddTime FROM Product AS ...

  6. 手写HashMap,快手面试官直呼内行!

    手写HashMap?这么狠,面试都卷到这种程度了? 第一次见到这个面试题,是在某个不方便透露姓名的Offer收割机大佬的文章: 这--我当时就麻了,我们都知道HashMap的数据结构是数组+链表+红黑 ...

  7. 读FCL源码系列之List<T>---让你知其所以然---内含疑问求大神指点

    序言 在.NET开发中,List<T>是我们经常用到的类型.前段时间看到其他部门小伙伴讨论“两个List(10W个元素)集合求并集,list1.Where(p=>list2.Cont ...

  8. 用纯函数式思维在Java8下写的一段奇葩程序

    首先说一下什么是纯函数式.在我的理解,"纯函数式"用一句话就可以描述:Anything is value.--我的理解不一定准确,但我就是这么理解的. 就是所有的东西都是值--没有 ...

  9. 学习 Doug Lea 大神写的——Scalable IO in Java

    学习 Doug Lea 大神写的--Scalable IO in Java 网络服务 Web services.分布式对象等等都具有相同的处理结构 Read request Decode reques ...

随机推荐

  1. C#LeetCode刷题之#720-词典中最长的单词(Longest Word in Dictionary)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4120 访问. 给出一个字符串数组words组成的一本英语词典.从 ...

  2. rocketMq安装及集群配置

    网上关于rocketMq安装.集群配置的文章有很多,作为一个初学者,跟着网上的各种教程安装遇到了各种坑,可谓是一路坎坷.本文记录下rocketMq安装的完整过程.希望对你有一点帮助 安装rocketM ...

  3. python设计模式之原型模式

    python设计模式之原型模式 ​ 对于原型模式而言,其中最主要的部分就是关于一个对象的复制,其中就包含两个方面:1.浅复制:2.深复制.具体的区别请看我相关的随笔.这里简略的说明一下,浅复制就等于对 ...

  4. 从零开始讲解JavaScript中作用域链的概念及用途

    从零开始讲解JavaScript中作用域链的概念及用途 引言 正文 一.执行环境 二.作用域链 三.块级作用域 四.其他情况 五.总结 结束语 引言 先点赞,再看博客,顺手可以点个关注. 微信公众号搜 ...

  5. Python日期时间(详细)

    获取当前时间戳 import time t = time.time() millis1 = int(t) print('10位时间戳:{}'.format(millis1)) millis2 = in ...

  6. 微信公众号请求code时报redirect_uri 参数错误

    (1) 检查微信公众号中"接口权限"--"网页授权获取用户基本信息"中的网页授权域名.域名不带http(s) (2)如果在拼接跳转到微信授权接口的URL时,使用 ...

  7. Robot Framework(6)——案例分层

    上一篇以gogomall的登录为例,记录了一个简单的登录流程的脚本,在实际应用中,当流程发生一些小的变动,或者前端代码改变,导致元素选择器失效,我们维护脚本的成本就比较大,需要一个一个去修改,所以,有 ...

  8. java爬取图片示例

    爬虫是什么 这里引用一下 wiki 中关于 网络爬虫的定义,相信大家看过后会有一个清晰的认识 网络爬虫(英语:web crawler),也叫网络蜘蛛(spider),是一种用来自动浏览万维网的网络机器 ...

  9. Java面试题(RabbitMQ篇)

    RabbitMQ 135. rabbitmq 的使用场景有哪些? ①. 跨系统的异步通信,所有需要异步交互的地方都可以使用消息队列.就像我们除了打电话(同步)以外,还需要发短信,发电子邮件(异步)的通 ...

  10. C++入门记-构造函数和析构函数

    前文回顾 本文档环境基于Vscode + GCC + CodeRunner 关于C++的环境搭建请参考下面链接: C++入门记-大纲 由于本人具有C#开发经验,部分相同的知识就不再赘述了.只列一下需要 ...