JDK不同版本有不同的特性,我刚毕业时候JDK1.8(8)已经出现了,但是大多公司还在用1.6(6),后面陆续出现了9、10、11、12,但是大多公司仍然坚守在1.6版本,逐渐在向1.8靠拢。
本篇讲述下一些1.6之后代码的风格,可以帮助你写出更优雅的代码。
如果大家正在寻找一个java的学习环境,或者在开发中遇到困难,可以加入我们的java学习圈,点击即可加入,共同学习,节约学习时间,减少很多在学习中遇到的难题。
JDK1.7的新特性有很多可取之处,比如
new HashMap<>
不用再写<>
中的类型了这里只说try-with-resource
,是因为用了这么久的try catch
,总是对try-with-resource
不放心,从第一天写代码就被告知,打开的流一定要关闭,不然就会内存泄漏。所以总是下意识去关闭流,但是try-with-resource
确告诉我们,用try-with-resource
包围的流,不需要关闭了!
try-with-resources
声明要求其中定义的变量实现 AutoCloseable 接口,这样系统可以自动调用它们的close方法,从而替代了finally中关闭资源的功能。可以查看下AutoCloseable这个接口: AutoCloseable:
/*
PeformMonthNormListReq::getNormId
指的是获取normId属性,s->s是指的stream当前遍历的元素当作map的value;这个方法可能报错(java.lang.IllegalStateException: Duplicate key),因为list中的元素是有可能重复的。toMap有个重载方法,可以传入一个合并的函数来解决key冲突问题:List<PeformMonthNormListReq> normParamList = xxxxx; Map<Integer, PeformMonthNormListReq> paramMap = normParamList.stream() .collect(Collectors.toMap(PeformMonthNormListReq::getNormId, Function.identity(), s -> s));这种是后者覆盖前者来解决key重复问题;3.5 parallelStream并行流,使用fork-join模式,分线程然后归并结果的一种方法。public Map<String, LineUserShort> getUserShortInfoMap(List<String> userList) { List<List<String>> partsList = Lists.partition(userList, 400); Map<String, LineUserShort> minMap = new ConcurrentHashMap<>(); partsList.parallelStream().forEach(list -> { List<LineUserShort> userList = lineUserMapper.selectByEnNameList(list,0); userList.stream().forEach(user -> { minMap.put(user.getMin(), user); }); }); return minMap; }上面的代码用了一个parallelStream和一个stream,它的逻辑是,先将list按400大小分成多个list,然后每个list并行去数据库中查询信息,查完放到map中;userList用stream而不用parallelStream是因为:在线程的开销和业务执行时间之间评估下是否有必要使用多线程操作。四、函数式接口Functionjdk8新特性加入了函数式接口,Function、Predicate等一大堆,除了jdk8中可以使用函数式接口,我们也可以用它来做一些爱做的事情。如我们先定义一个BiFunction,连接将k和v放到数组中,逗号分隔:BiFunction<Integer, String, String> func = (k,v) -> String.join(",", Arrays.asList(String.valueOf(k), v));然后把BiFunction当作参数传递给方法。方法直接调用即可按照BiFunction设定的逻辑去执行。public String doSomeThing(BiFunction<Integer, String, String> func) { return func.apply(1, "heihei"); }其他函数略不同,用法相同。Lambda表达式和函数式接口是可以对应起来的,如: 1. Function接口,可以通过 s->xxx
来调用; 2. BiFunction接口,可以通过 (k,v)->xxx
来调用;五、jdk8中Collection和Map的一些精简方法5.1 Collectione的removeIfSet<LineUserInfo> userList = xxxx; userList.removeIf(s -> lineUserMapper.selectByName(s.getMin(), 0) != null);上面这段代码,是过滤掉selectByName能查询到的人员。5.2 Map的getOrDefaultMap<Integer,String> userMap = xxxx; String name = userMap.getOrDefault(1, "路人甲");上面这段代码,是获取id为1的name,如果不存在,返回"路人甲",注意,这里只是给个默认返回值,并不会保存到map里。5.3 Map的computeIfAbsentMap<Integer,String> userMap = xxxx; String name = userMap.computeIfAbsent(1, k -> "路人甲");上面这段代码,是获取id为1的name,如果不存在,存入字符串"路人甲",并返回。注意,这里是会将默认值写入的。5.4 Map的compute和computeIfPresentMap<Integer,String> userMap = xxxx; String name = userMap.compute(1, (k,v) -> "路人甲");Map<Integer,String> userMap = xxxx;
String name = userMap.computeIfPresent(1, (k,v) -> "路人甲");
1. compute的方法,不管key存不存在,操作完成后保存到map中;
2. computeIfPresent 的方法,对指定的在map中已经存在的key的value进行操作。只对已经存在key的进行操作,其他不操作
这两个方法都是用的BiFunction,所以要用```(k,v) -> ```这种兰布达表达式。
#### 5.5 Map的merge
```java
Map<Integer, String> userMap = new HashMap<>();
String name = userMap.computeIfAbsent(1, k -> "路人甲");
name = "路人乙";
userMap.merge(1, name, (k, v) -> String.join(",", k, v));
上面这段代码,是将userMap中的历史数据和现有数据,通过传入的BiFunction进行合并,怎么合并是BiFunction说了算。
### 六、Optional接口
Optional是JDK8新增的接口,其实啥额外的功能都没有,还可能会让你的代码多写几行,但是它是为不喜欢检查null的人设计的,一些对象如果是null,使用的时候就会抛出NullPointerException,所以如果返回了Optional<T>,按照它的常规使用方法,必然是先判断一下了。
较新版本的JPA查询都是返回的Optional接口了。
```java
Optional<Integer> optional = Optional.ofNullable(1);
if(optional.isPresent()){
Integer a = optional.get();
}
至于Optional其他的map、orElseGet方法,一眼就明白了,这里不讲。
有人说JDK8的日期API也很好啊,的确还可以,但是这套接口仍存在兼容性问题:
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
转换mybatis-typehandlers-jsr310
,而且,如果mybatis版本小于3.4.0,还需要额外配置日期API的typeHandler;大于3.4.5,jsr310和typeHandler就都不需要额外配置了;@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
转换;至于JDK9及以上,我想国内用到的企业屈指可数,我也没研究过。