前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >让代码更优雅:JAVA代码不同JDK版本的不同写法

让代码更优雅:JAVA代码不同JDK版本的不同写法

作者头像
品茗IT
发布2020-09-22 10:26:42
9690
发布2020-09-22 10:26:42
举报
文章被收录于专栏:品茗IT

让代码更优雅:JAVA代码不同JDK版本的不同写法

一、概述

JDK不同版本有不同的特性,我刚毕业时候JDK1.8(8)已经出现了,但是大多公司还在用1.6(6),后面陆续出现了9、10、11、12,但是大多公司仍然坚守在1.6版本,逐渐在向1.8靠拢。

本篇讲述下一些1.6之后代码的风格,可以帮助你写出更优雅的代码。

如果大家正在寻找一个java的学习环境,或者在开发中遇到困难,可以加入我们的java学习圈,点击即可加入,共同学习,节约学习时间,减少很多在学习中遇到的难题。

二、try-with-resource

JDK1.7的新特性有很多可取之处,比如

  1. 泛型实例的创建可以通过类型推断来简化,如new HashMap<>不用再写<>中的类型了
  2. switch可以使用string
  3. 并发工具增强
  4. Catch多个异常,单个catch块中处理多个异常
  5. try-with-resources.
  6. 等等等

这里只说try-with-resource,是因为用了这么久的try catch,总是对try-with-resource不放心,从第一天写代码就被告知,打开的流一定要关闭,不然就会内存泄漏。所以总是下意识去关闭流,但是try-with-resource确告诉我们,用try-with-resource包围的流,不需要关闭了!

try-with-resources 声明要求其中定义的变量实现 AutoCloseable 接口,这样系统可以自动调用它们的close方法,从而替代了finally中关闭资源的功能。可以查看下AutoCloseable这个接口: AutoCloseable:

/*

  • @author Josh Bloch那么,都有什么类实现了这个接口呢? 如图,太多了,看这些没啥用,一般我们用到的流,都实现了Closeable接口,这个接口也继承了AutoCloseable。 所以,我们就可以这样写: ```java public static void copy(String src, String dst) { try (InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dst)) { byte[] buff = new byte[1024]; int n; while ((n = in.read(buff)) >= 0) { out.write(buff, 0, n); } } catch (IOException e) { e.printStackTrace(); } }InputStream和OutputStream都实现了Closeable接口,也就实现了AutoCloseable这个接口,所以上面的代码就不需要写finally了,也不需要手动close了。注意需要关闭的流,必须写在try(...)中。三、stream流stream流是jdk8的新特性,stream流更像一个高级版本的 Iterator,可以很方便地为我们提供各种操作。3.1 List转另外一个List3.1.1 mapList<PerformTemplateNorm> normDbList = xxxxxx; List<String> fieldList = normDbList.stream().map(s -> s.getNormName()).collect(Collectors.toList());上面的这段代码,将normDbList的normName属性取出来,重整成新的list。3.1.2 filterList<PerformTemplateNorm> normDbList = xxxxxx; List<PerformTemplateNorm> fieldList = normDbList.stream().filter(t -> t.getMainDepartment() == 1).collect(Collectors.toList());上面的这段代码,将normDbList的mainDepartment属性为1保留,过滤掉为0的,重整成新的list。3.2 List遍历List<FirstLineUserShort> userList = xxxx; userList.stream().forEach(user -> { minMap.put(user.getMin(), user); });用forEach遍历。3.3 List排序List<PerformMonthStaticsRes> resList = xxxxxx; resList.stream().sorted(Comparator.comparing(s -> Integer.parseInt(s.getMonth()))) .collect(Collectors.toList());上面这段代码是根据resList的month属性转成整型后的大小排序。默认升序。3.4 List转MapList<PeformMonthNormListReq> normParamList = xxxxx; Map<Integer, PeformMonthNormListReq> paramMap = normParamList.stream() .collect(Collectors.toMap(PeformMonthNormListReq::getNormId, s -> s));上面这段代码里,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) -> "路人甲");
  • @since 1.7 */ public interface AutoCloseable { void close() throws Exception; }

Map<Integer,String> userMap = xxxx;

String name = userMap.computeIfPresent(1, (k,v) -> "路人甲");

代码语言:javascript
复制
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));

代码语言:javascript
复制
上面这段代码,是将userMap中的历史数据和现有数据,通过传入的BiFunction进行合并,怎么合并是BiFunction说了算。
### 六、Optional接口
Optional是JDK8新增的接口,其实啥额外的功能都没有,还可能会让你的代码多写几行,但是它是为不喜欢检查null的人设计的,一些对象如果是null,使用的时候就会抛出NullPointerException,所以如果返回了Optional<T>,按照它的常规使用方法,必然是先判断一下了。

较新版本的JPA查询都是返回的Optional接口了。

```java

Optional<Integer> optional = Optional.ofNullable(1);

if(optional.isPresent()){

代码语言:javascript
复制
Integer a = optional.get();

}

代码语言:javascript
复制

至于Optional其他的map、orElseGet方法,一眼就明白了,这里不讲。

其他说明

有人说JDK8的日期API也很好啊,的确还可以,但是这套接口仍存在兼容性问题:

  1. fastjson最新版本1.2.73无法使用@JSONField(format = "yyyy-MM-dd HH:mm:ss")转换
  2. mybatis使用需要引入mybatis-typehandlers-jsr310,而且,如果mybatis版本小于3.4.0,还需要额外配置日期API的typeHandler;大于3.4.5,jsr310和typeHandler就都不需要额外配置了;
  3. fastxml也无法使用@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")转换;

至于JDK9及以上,我想国内用到的企业屈指可数,我也没研究过。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/09/21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 让代码更优雅:JAVA代码不同JDK版本的不同写法
  • 一、概述
  • 二、try-with-resource
  • 其他说明
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档