业务背景
  首先,业务需求是这样的,从第三方电商平台拉取所有订单,然后保存到公司自己的数据库,需要判断是否有物流信息,如果有物流信息,还需要再进行上传。
  而第三方接口返回的数据是 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. QUIC协议详解之Initial包的处理

    从服务器发起请求开始追踪,细说数据包在 QUIC 协议中经历的每一步.大量实例代码展示,简明易懂了解 QUIC. 前言 本文介绍了在 QUIC 服务器在收到 QUIC 客户端发起的第一个 UDP 请求 ...

  2. 在 Go 语言中,我为什么使用接口

    强调一下是我个人的见解以及接口在 Go 语言中的意义. 如果您写代码已经有了一段时间,我可能不需要过多解释接口所带来的好处,但是在深入探讨 Go 语言中的接口前,我想花一两分钟先来简单介绍一下接口. ...

  3. SG 函数学习

    \(Mex\) 运算 \(mex(S)\) 为不属于集合 \(S\) 的最小非负整数,即: \[mex(S)=\min \limits_{x \in \mathbb{N},x \not\in S} \ ...

  4. HotSpot的执行引擎-CallStub栈帧

    之前多次提到接触到调用JavaCalls::call()方法来执行Java方法,如: (1)Java主类装载时,调用JavaCalls::call()方法执行的Java方法checkAndLoadMa ...

  5. Visual Studio自动编译gRPC工程的设置

    前段时间研究一个java程序,增加一些功能.其中用到java和C#的通信.自然,有多种办法,后来实际上是用javascript调用C#的REST WCF服务实现的.但是在查资料的过程中,发现有个Pro ...

  6. git pull冲突的解决方案

    处理步骤: 1.先将本地修改存储起来 $ git stash 这样本地的所有修改就都被暂时存储起来 .使用git stash list可以看到保存的信息: git stash暂存修改 其中stash@ ...

  7. CSP-J2019 NOIP普及组初赛真题(选择题部分)

    NOIP初赛考试提纲 时间:10月的第2/3个星期六下午14:30~16:30 分数及形式:满分100分,形式为笔试(今年可能上机) 1.单项选择题,共15题,每题2分,共30分 2.阅读程序题,共3 ...

  8. linux 基本命令整理--转

      推荐:http://www.cnblogs.com/lingiu/p/3446647.html 1. 查看目录文件:ls2. 查看目前路径:psw3. 查看文件内容:cat 文件名4. 打开编辑器 ...

  9. 手写一个简单版的SpringMVC

    一 写在前面 这是自己实现一个简单的具有SpringMVC功能的小Demo,主要实现效果是; 自己定义的实现效果是通过浏览器地址传一个name参数,打印“my name is”+name参数.不使用S ...

  10. 玩转Spring——Spring整合JDBC

    传统JDBC代码的弊端在传统的jdbc代码中,即使是执行一条简单的SQL语句,其实现的整个流程也是极为繁琐的,先打开数据库连接执行sql,然后组装结果,最后关闭数据库资源,这中间还有大量的try... ...