Java8 几个很好用的方法,真的很香

待兔 等级 946 1 0
标签: jdk8Java

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

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

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

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

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

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

Java8 几个很好用的方法,真的很香

预防空指针问题

日常开发中我们通常会从 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有一个好处,针对传入 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 函数,不熟悉的话,其实比较难以理解代码。

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

最后,JDK8 还有许多好用方法,刻意简化代码开发,你可以在留言区推荐几个吗?

收藏
评论区

相关推荐

Java8 几个很好用的方法,真的很香
JDK8 应该是 Java 中最坚挺一个版本,这个版本新增很多特性,让我们开发起来多了很多便利。 不过最近 Review 项目代码的时候发现,虽然很多项目工程已经使用了 JDK8,但是工程代码却很少使用到 JDK8 新特性、新方法。 如果单从代码正确性上来说,老方式写法写当然没有什么问题,那唯一的缺点其实就是代码行数比较多,比较繁琐。 那同样的需求,使
java中List数组遍历删除
List数组遍历删除 环境 jdk8 junit 单元测试 正解java// 正解1, jdk自带的addAll方法 @Test public void test18() { String strs {"12","34","56","78","90"}; List<String list Ar
JDK 从老版本升级到 1.8的问题总结
![](https://oscimg.oschina.net/oscnet/fcd31648-309f-48f1-90b8-8f02b92fa027.png) JDK8 升级常见问题 -------------- > JDK8 发布很久了,它提供了许多吸引人的新特性,能够提高编程效率。 > > 如果是新的项目,使用 JDK8 当然是最好的选择。但
JDK安装说明
JEESNS是使用JAVA开发的,所以需要运行JEESNS需要先安装JDK,JDK版本需要1.7或以上, 下载地址:[http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html](https://www.oschina.net/action/GoTo
Java 8中处理日期和时间示例
在Java 8以前,日期和时间处理一直被广大java程序员抱怨太难用,首先是`java.util`和`java.sql`中,都包含`Date`类,如果要处理`java.text.DateFormat`类处理。同时`java.util.Date`中既包含了日期,又包含了时间,所以java8新的日期和时间库,很好的解决了以前日期和时间类的很多弊端。并且也借鉴了第
Java 之路 Day3 JAVA环境的搭建
JAVA环境的搭建 ========= * * * 卸载JDK(了解JDK环境的组成) ----------------- 1. 删除Java的安装目录 2. 删除JAVA\_HOME 3. 删除path下关于Java的目录 4. 通过cmd打开dos窗口检测java-version是否删除 安装JDK
Java8中的简易并发
Java8中的简易并发  分享到: 5 本文由 ImportNew - kingviker 翻译自 jaxenter。欢迎加入Java小组。转载请参见文章末尾的要求。 有人曾经说过(很抱歉,我们找不到原句了): 初级程序员认为并发很难。 中级程序员认为并发很简单。 高级程序员认为并发很难。 这说的很对。但是从好的方面来看
Java8中的简易并发
**我们在《实战Java高并发程序设计》一书中,专门介绍过java 8中对并发的改进。这里我通过转载一篇博客来说简单介绍下。** 有人曾经说过(很抱歉,我们找不到原句了): > 初级程序员认为并发很难。 > 中级程序员认为并发很简单。 > 高级程序员认为并发很难。 这说的很对。但是从好的方面来看,Java8为我们带来了转机,通过lamb
Java日期时间API系列19
  通过[Java日期时间API系列6-----Jdk8中java.time包中的新的日期时间API类](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.cnblogs.com%2Fxkzhangsanx%2Fp%2F12052195.html)中时间范围示意图:可以很清晰的看出Zo
Java服务安装包下载
jdk-8u221-linux-x64.tar.gz  [https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.or
java8之后的时间api
* * * title: java8中更好的处理时间方式 date: 2018-08-06 11:33:43 tags: java ---------- java8中关于时间的操作提供了新的api,相比之前感觉有了很多的提升。 以下内容转自: [https://www.liaoxuefeng.com/article/001419392
jdk8 optional
Optional 是jdk1.8(新命名方式应该说 JDK8)推出的解决空指针问题的类,解决空指针这个说法不是准确,应该说是方便简洁处理空指针问题吧。毕竟jdk8推出了很多新语言使java语言编写程序更加简洁。 参考:[https://www.jianshu.com/p/d81a5f7c9c4e](https://www.oschina.net/action
Ubuntu配置JavaWeb开发环境(JDK8+eclipse+maven+Tomcat7)
#### 1、查看系统是32位还是64位 sudo uname --m root用户下可以不加sudo 显示结果为i686则为32位系统,结果为x86\_64则为64位 #### 2、下载JDK8 [http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-
Cubieboard 3(cubietruck) 安装 java 环境
Cubieboard 3  刷机过程  请看  [http://name5566.com/4398.html](https://www.oschina.net/action/GoToLink?url=http%3A%2F%2Fname5566.com%2F4398.html) 安装 java 环境 下载  arm jdk [h
Jenkins:批量自动将 Maven 类型 Job 迁移到自由风格类型
为什么要迁移? ------- 近期进行 Jenkins 从1.X到2.X的升级演练 Jenkins2 最新版本只能在 JDK8 或 JDK11 版本下运行,我所使用的 JDK 版本为 JDK8 在构建 Maven Job,Job 配置的 JDK 版本为 JDK7时,构建报错 $ /usr/local/java/bin/java -cp