JDK8 应该是 Java 中最坚挺一个版本,这个版本新增很多特性,让我们开发起来多了很多便利。

不过最近 Review 项目代码的时候发现,虽然很多项目工程已经使用了 JDK8,但是工程代码却很少使用到 JDK8 新特性、新方法。

如果单从代码正确性上来说,老方式写法写当然没有什么问题,那唯一的缺点其实就是代码行数比较多,比较繁琐。

那同样的需求,使用 JDK8 新方法,其实几行代码就可以搞定,这样代码就会变得非常简洁。

今天就以三个比较常见的场景为例,教你几招,使用 JDK8 Map新增的方法简化代码开发。

下面就来看看这次即将用到 Map几个新方法:

欢迎关注我的公众号:小黑十一点半,获得日常干货推送。如果您对我的专题内容感兴趣,也可以关注我的博客:studyidea.cn

预防空指针问题

日常开发中我们通常会从 Map获取元素,然后进行相关的业务处理,示例代码如下:

Map<String, String> map = new HashMap();
map.put("公号", "小黑十一点半");
map.put("主理人", "楼下小黑哥");
// 可能存在 NPE 问题
System.out.println(map.get("支付").toUpperCase());
复制代码

如果就像示例代码直接处理,一旦 Map中相应元素不存在,那么我们就会碰到空指针问题。

为了解决这个问题,通常我们可以先判断一下元素是否为 null,如果不为 null,再做相应的业务处理。

// 第一种 if 判空
String value = map.get("支付");
if (!Objects.isNull(value)) {System.out.println(value.toUpperCase());
}
复制代码

这种方式唯一劣势就是代码处理上比较繁琐,不是很简洁。

所以针对这种情况,其实可以使用条件运算符,设置一个默认空值,从而避免后续处理发生空指针。

// 第一种 if 判空
String value = map.get("支付");
// 第二种 条件运算符
value = Objects.isNull(value) ? "" : value;
复制代码

这种方式比较简洁,所以日常开发中我比较喜欢用这种方式。

ps: 这里的前提,空字符串对于业务没有特殊意义。如果存在特殊意义,那就不能使用这种方式了。

那如果使用 JDK8 ,其实就很方便了,我们就可以使用 Map#getOrDefault直接代替条件运算符。

// 等同于条件运算符的效果: Objects.isNull(value) ? "" : value;
String value = map.getOrDefault("支付","");
复制代码

借助 Map#getOrDefault 一行代码直接搞定,就是这么简单。

如果你还在使用 JDK8 之前的版本,没办法使用这个方法。没关系,我们可以借助 Apache Common-Lang3 提供的工具类 MapUtils 避免空指针。

// Apache MapUtils
String value = MapUtils.getString(map, "支付", "");
复制代码

MapUtils这个工具类相对于Map#getOrDefault有一个好处,针对传入 Map为 null 的情况,可以设置默认值。

假设我们是从 POJO对象获取 Map 参数,这个时候为了防止空指针,我们就需要提前做一个空指针的判断。

不过如果使用 MapUtils,那我们就不需要判断是否为 null,方法内部已经封装这个逻辑。

MapUtils.getString(pojo.getMap(),"支付", "");
复制代码

巧用 computeIfAbsent

日常开发中,我们会碰到这类场景,需要一个键需要映射到多个值,这个时候我们可以使用 Map<K, List<V>>这个结构。

此时添加元素的时候,我们需要做一些判断,当内部元素不存在时候主动创建一个集合对象,示例代码如下:

Map<String, List<String>> map = new HashMap();List<String> classify = map.get("java框架");
if (Objects.isNull(classify)) {classify = new ArrayList<>();classify.add("Spring");map.put("java框架", classify);
} else {classify.add("Spring");
}
复制代码

上面的代码比较繁琐,到了 JDK8,Map新增一个 computeIfAbsent方法:

default V computeIfAbsent(K key,Function<? super K, ? extends V> mappingFunction) {
复制代码

如果 Map中 key 对应的 value 不存在,则会将 mappingFunction 计算产生的值作为保存为该 key 的 value,并且返回该值。否则不作任何计算,将会直接返回 key 对应的 value。

利用这个特性,我们可以直接使用 Map#computeIfAbsent一行代码完成上面的场景,示例代码如下:

map.computeIfAbsent("java框架", key -> new ArrayList<>()).add("Spring");
复制代码

那其实 Map 中还有一个方法 putIfAbsent,功能跟 computeIfAbsent比较类似。

那刚开始使用的时候,误以为可以使用 putIfAbsent完成上面的需求:

// ERROR:会有 NPE 问题
map.putIfAbsent("java框架", new ArrayList<>()).add("Spring");
复制代码

那其实这是错误的,当 Map 中 key 对应 value 不存在的时候,putIfAbsent将会直接返回 null

而 computeIfAbsent将会返回 mappingFunction计算之后的值,像上面的场景直接返回就是 new ArrayList

这一点需要注意一下,切勿用错方法,导致空指针。

最后针对上面这种一个键需要映射到多个值,其实还有一个更优秀的解决办法,使用 Google Guava 提供的新集合类型 Multiset,以此快速完成一个键需要映射到多个值的场景。

示例代码如下:

ArrayListMultimap<Object, Object> multiset= ArrayListMultimap.create();
multiset.put("java框架","Spring");
multiset.put("java框架","Mybatis");
// java框架--->Spring,Mybatis
复制代码

单词统计

假设有如下需求,我们需要统计一段文字中相关单词出现的次数。那实现方式其实很简单,使用 Map存储相关单词的次数即可,示例代码如下:

Map<String, Integer> countMap = new HashMap();
Integer count = countMap.get("java");
if (Objects.isNull(count)) {countMap.put("java", 1);
} else {countMap.put("java", count++);
}
复制代码

这类代码是不是很熟悉?同样比较繁琐。

接下来我们可以使用 JDK8 Map 新增方法进行改造,这次使用上面用过的 getOrDefault 再加 put 方法快速解决,示例代码如下:

// getOrDefault
Integer count = countMap.getOrDefault("java",0);
countMap.put("java", count + 1);
复制代码

那其实我们还有一种办法,这次我们使用 Map#merge这个新方法,一句代码完成上述需求,示例代码如下:

countMap.merge("java", 1, Integer::sum);
复制代码

说真的,刚看到 merge这个方法的时候还是有点懵,尤其后面直接使用 lambda 函数,让人不是很好理解。

这里先将lambda 函数还原成正常类,给大家着重解释一下这个方法:

countMap.merge("java", 1, new BiFunction<Integer, Integer, Integer>() {@Overridepublic Integer apply(Integer oldValue, Integer newValue) {return Integer.sum(oldValue,newValue);}
});
复制代码

用上面代码说明一下merge方法,如果 java这个值在 countMap中不存在,那么将会其对应的 value 设置为 1。

那如果 java 在 countMap 中存在,则会调用第三个参数 remappingFunction 函数方法进行计算。

remappingFunction 函数中,oldValue代表原先 countMap 中 java 的值,newValue代表我们设置第二个参数 1,这里我们将两者相加,刚好完成累加的需求。

最后

这次主要从个人日常碰到三个场景出发,给大家对比了一下使用 JDK8 Map 新增方法只会,两者代码区别。

从上面可以很明显看出,使用新增方法之后,我们可以用很少的代码可以完成,整体看起来变得非常简洁。

不过 JDK8 之后很多方法都会用到 lambda 函数,不熟悉的话,其实比较难以理解代码。

不过也还好,我们只要在日常编码过程中,刻意去练习使用,很快就能上手。

本文首发于java黑洞网,博客园同步更新

别再这么写代码了,这几个方法不香吗?相关推荐

  1. 腾讯万字Code Review规范出炉!别再乱写代码了

    本文经公众号:腾讯技术工程(ID:Tencent_TEG)授权转载,如需转载请联系出处. 作者:cheaterlin,腾讯 PCG 后台开发工程师 前言 作为公司代码委员会 golang 分会的理事, ...

  2. 有赞996反省:男程序员们,别再低头写代码了(上)

    近日,一条"有赞年会亲历"的帖子在知乎刷屏,关于有赞年会上宣布的年后开始执行"996"工作制度的消息,引发了有赞乃至整个互联网员工激烈吐槽. 什么是" ...

  3. 有赞996刷屏:男程序员们,别再低头写代码了

    近日,一条"有赞年会亲历"的帖子在知乎刷屏,关于有赞年会上宣布的年后开始执行"996"工作制度的消息,引发了有赞乃至整个互联网员工激烈吐槽. 图片: mmbiz ...

  4. idea自动补全代码,一秒生成new List,写代码更便捷,快捷方法!

    自动补全List<lo> xx = new Arraylist<>(); 点击设置 点击编译器选中后缀补全,点击+号 选中java 上面的list是快捷方式 下面需要补全的就是 ...

  5. 【怎样写代码】小技巧 -- 关于方法中修饰形参的关键词

    如果喜欢这里的内容,你能够给我最大的帮助就是转发,告诉你的朋友,鼓励他们一起来学习. If you like the content here, you can give me the greates ...

  6. 我为什么晚上写代码?

    摘要:作为一个有点追求的程序员,应该每天练习写代码,而夜深人静的时候,似乎比较合适,至少对我来说是这样. 我可真没时间写代码 写代码是我的工作,也是我的兴趣,本来以为,我应该可以一直写下去. 然而,现 ...

  7. ​坚持写代码,这是晋级大师的唯一方法。

    作者 | Roberto 译者 | 弯月,责编 | 郭芮 出品 | CSDN(ID:CSDNnews) 以下为译文: 初级开发人员: 你好! 提笔给你写这封信的时候,可能你梦想的开发人员职业生涯才刚刚 ...

  8. 致初级开发者的一封信:坚持写代码!

    坚持写代码,这是晋级大师的唯一方法. 作者 | Roberto 译者 | 弯月,责编 | 郭芮 出品 | CSDN(ID:CSDNnews) 以下为译文: 初级开发人员: 你好! 提笔给你写这封信的时 ...

  9. 别以为程序员的工作就是写代码

    大家好,我是鱼皮,今天给大家分享一个开发小经验. 很多没有实际工作过的同学,可能都会认为程序员的工作只有写代码 + 和产品经理 "拉扯",也会习惯性地用代码量来评价一个程序员的工作 ...

最新文章

  1. 4月全球操作系统市场份额:Win 7份额连续4月上涨
  2. 论文笔记之:Deep Attributes Driven Multi-Camera Person Re-identification
  3. TTS语音播报程序部署与配置
  4. Faster R-CNN
  5. AndroidStudio导入新项目一直卡在Building gradle project
  6. 阿里云全球发布5大举措!
  7. 随机森林的特征 是放回抽样么_机器学习超详细实践攻略(10):随机森林算法详解及小白都能看懂的调参指南...
  8. 自定义 BaseServlet,通用Servlet的抽取,模块化开发Servlet
  9. android 发送按键 0,android monitor tool (8.0 模拟发送按键及触摸屏事件实现)
  10. 文本聚类python fcm_机器学习笔记----Fuzzy c-means(FCM)模糊聚类详解及matlab实现
  11. [模板]线性筛素数(欧拉筛法)
  12. Guthrie QA-CAD2019(CAD绘图修订管理工具)A.04中文版
  13. 什么是ISBN码及如何制作
  14. java 无法加载主类
  15. Docker容器实现跨主机文件共享(NFS服务器)
  16. MySQL主从复制与读写分离配置及实操
  17. k8s集群svc端口范围,nfs做StorageClass运行故障
  18. 可能是颜值最高的微信Markdown编辑器,用Markdown的你一定会爱上
  19. Mybatis搞两下(sqlsession,动态代理)
  20. linux 相机软件,镜像相机app

热门文章

  1. ASP.NET常用语句1--20条 非常实用
  2. [股市]跳搂指数(收藏)
  3. python学习笔记全过程_Python学习笔记一(Hello World)
  4. hbuilderx内置服务器启动失败_我们来看看Swoole是如何实现WebSocket服务器及客户端的...
  5. (41)Xilinx MMCM IP核配置(二)(第9天)
  6. html加css绘制oprea的logo,拾人牙慧 – CSS3实现Opera浏览器的logo
  7. 9.FreeRTOS学习笔记-任务通知
  8. vs2010 导出创建dll 导入使用dll 导出有命名空间的类 函数 外部函数
  9. 以太网帧的最小长度_802.3?以太网?看完你就懂了
  10. 【蓝桥杯单片机】Led+蜂鸣器+继电器