【Java 8 新特性实践】Optional 实践 0x01,“为什么我说 Java8 新特性不能乱用”

引入

今天在一份祖传代码,看到其中对 map 调用了 3 次,十分想 polish 掉它,脱敏后如下:

boolean oneBoolean = true;
Map<String, String> fMap = oneDTO.getFeatureMap();
if (fMap != null && fMap.containsKey("oneKey") && StringUtils.isNumeric(fMap.get("oneKey"))) {
    Long options = Long.valueOf(fMap.get("oneKey"));
    if (options != null && ((options>>>48) & 1) == 1) {
        // 第48位为1,表示"一种特殊的含义"
        needSplit = false;
    }
}

做法

想到以前看过的 Optional 的用法,突然想练练手(一般不可能 Push 改掉,代码变更在企业永远要经过回归测试才能上线,而回归测试意味着成本。“能跑的代码,不能改”)

正确地用 Java8,这种场景需要用反逻辑

boolean oneBoolean1 = ! Optional.ofNullable(oneDTO.getFeatureMap()).map(map -> map.get("oneKey"))
	.filter(StringUtils::isNumeric).map(Long::parseLong).filter(options -> ((options >>> 48) & 1) == 1).isPresent();

如果有个人想把反逻辑放进filter里转正逻辑,而没有经过思考,就会错

boolean oneBoolean2_error =   Optional.ofNullable(oneDTO.getFeatureMap()).map(map -> map.get("oneKey"))
	.filter(StringUtils::isNumeric).map(Long::parseLong).filter(options -> ((options >>> 48) & 1) != 1).isPresent();

测试

异常 CASE:中间链里出现 null 时,导致最终结果 : oneBoolean=true, oneBoolean1=true, oneBoolean2_error=false;

oneBoolean2 修正错误后

boolean oneBoolean3 = Optional.ofNullable(fulfillWareDTO.getFeatureMap()).map(map -> map.get("oneKey"))
	.filter(StringUtils::isNumeric).map(Long::parseLong).map(options -> ((options >>> 48) & 1) != 1).orElse(true);

结论

使用 Java8 中的 Optional、函数式编程等各种特性,编码的花样多了,对编码者的要求也高了。
如果不是特别熟练,建议还是只停留在使用传统的编码方式,比如使用上述祖传代码的"卫语句"形式,不要想着用"花里胡哨"的东西,除非你很熟练。

意义:养成一种习惯,在看到祖传代码的时候,思考它,想着改进它,尽管你不能去 push 覆盖掉。但是你自己写的时候,就不会写出这样的代码了。

所以本文的真正标题其实应该是《如何对待你的祖传代码》(标题党 [doge][doge][doge]
那么回过头来,开头的祖传代码中用了 3 次 map 的操作,在生产链路上,3 次 和 1 次成本差距虽然很微毫,但是思考 3 次优化到 1 次写法的过程十分有益:

boolean oneBoolean4 = true;
Map<String, String> fMap2 = fulfillWareDTO.getFeatureMap();
if (fMap2 != null) {
    String oneValue = fMap2.get("oneKey");
    if (StringUtils.isNumeric(oneValue) && ((Long.parseLong(oneValue) >>> 48) & 1) == 1) {
        needSplit = false;
    }
}

用 Optional 熟练之后可以这样写(我个人认为的,铁子们有更好的想法可以提出讨论)

boolean oneBoolean5 = true;
if (Optional.ofNullable(oneDTO.getFeatureMap()).map(map -> map.get("oneKey")).filter(StringUtils::isNumeric)
		.map(Long::parseLong).map(options -> ((options >>> 48) & 1) == 1).orElse(false)) {
    oneBoolean5 = false;
}

更多实战

一些建议

对使用 Optional 的一些建议:

  • 永远不要在 Optional 链后使用 .get(),而是使用 .orElse() 或者 .orElseGet()
    • 仔细看看 .get() 就会发现为 null 时会报异常,使用 Optional 本身是为了避免不断地卫语句判 null 或者 try-catch 驱动

尾巴

好的,感谢你看到这里,对文章有错误的地方欢迎指出,谢谢。
如果觉得本文写得不错,不妨点赞、评论、收藏、分享,你的三连是对我最大的支持!

我的 Github:zhangt2333’s Github
我的 CSDN:zhangt2333’s CSDN
我的 博客园:zhangt2333’s cnblog
我的 小书房:https://zhangt.top/

本文作者:zhangt2333
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议 。转载请注明出处!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值