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

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

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

若是单从代码正确性上来讲,老方式写法写固然没有什么问题,那惟一的缺点其实就是代码行数比较多,比较繁琐。框架

那一样的需求,使用 JDK8 新方法,其实几行代码就能够搞定,这样代码就会变得很是简洁。ide

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

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

欢迎关注个人公众号:小黑十一点半,得到平常干货推送。若是您对个人专题内容感兴趣,也能够关注个人博客:studyidea.cn编码

预防空指针问题

平常开发中咱们一般会从 Map获取元素,而后进行相关的业务处理,示例代码以下:idea

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

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

为了解决这个问题,一般咱们能够先判断一下元素是否为 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有一个好处,针对传入 Mapnull 的状况,能够设置默认值。

假设咱们是从 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) { 复制代码

若是 Mapkey 对应的 value 不存在,则会将 mappingFunction 计算产生的值做为保存为该 keyvalue,而且返回该值。不然不做任何计算,将会直接返回 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"); 复制代码

那其实这是错误的,当 Mapkey 对应 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>() { @Override public Integer apply(Integer oldValue, Integer newValue) { return Integer.sum(oldValue,newValue); } }); 复制代码

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

那若是 javacountMap 中存在,则会调用第三个参数 remappingFunction 函数方法进行计算。

remappingFunction 函数中,oldValue表明原先 countMapjava 的值,newValue表明咱们设置第二个参数 1,这里咱们将二者相加,恰好完成累加的需求。

最后

此次主要从我的平常碰到三个场景出发,给你们对比了一下使用 JDK8 Map 新增方法只会,二者代码区别。

从上面能够很明显看出,使用新增方法以后,咱们能够用不多的代码能够完成,总体看起来变得很是简洁。

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

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



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

相关文章
相关标签/搜索