每天早上七点三十,准时推送干货
最近公司来了一批实习生,阿粉负责带一个。这位小师弟说实话,基本功很扎实,做事也非常靠谱,深得阿粉真传。
不过最近给其 Review 代码的时候,阿粉发现小师弟有些代码逻辑有些繁琐,有些代码阿粉看来可以用一些开源工具类实现,不需要自己重复实现。
不过这也是正常的,阿粉刚入行的时候写的代码也是这样,这几年慢慢接触了一些开源工具类,逐渐积累。现在写代码才会直接用工具类替换自己实现的这些繁琐的逻辑。
于是阿粉给小师弟分享了几个自己常用的开源工具类,小师弟学完直呼:『666』。
这里阿粉抛砖引玉,分享几个常用的工具类,希望帮助到刚入行的同学们。其他编程老司机如果还有其他好用的工具类,欢迎评论区分享。
下文主要分享这几个方向的常用工具类:
字符串相关工具类
Java 中 String 应该是日常用的最多一个类吧,平常我们很多代码需要围绕 String ,做一些处理。
JDK 提供 String API 虽然比较多,但是功能比较基础,通常我们需要结合 String 多个方法才能完成一个业务功能。
下面介绍一下 Apache 提供的一个工具类 StringUtils.
Maven Pom 信息如下:
1 | <dependency> |
commons-lang 有两个版本,一个是 commons-lang3 ,一个是 commons-lang 。
commons-lang 是老版本,已经很久没有维护了。
commons-lang3 是一直在维护的版本,推荐直接使用这个版本。
注意:如果你系统已经有 commons-lang,注意如果直接替换成 commons-lang3,将会编译错误。commons-lang3 中相关类与 commons-lang 一样,但是包名不一样。
判断字符串是否为空
判断字符串是否为空,想必每个人应该都写过吧:
1 | if (null == str || str.isEmpty()) { |
虽然这段代码非常简单,但是说实话,阿粉以前还是在这里犯过空指针的异常的。
使用 StringUtils ,上面代码可以替换下面这样:
1 | if (StringUtils.isEmpty(str)) { |
StringUtils 内部还有一个方法 isBlank
,也是用来判断字符串是否为空,两个方法比较相近,比较搞混,主要区别如下:
1 | // 如果字符串都是空格的话, |
判断字符串是否为空,使用频率非常高,这里大家可以使用 IDEA Prefix 的功能,输入直接生成判空语句。
字符串固定长度
这个通常用于字符串需要固定长度的场景,比如需要固定长度字符串作为流水号,若流水号长度不足,,左边补 0 。
这里当然可以使用 String#format
方法,不过阿粉觉得比较麻烦,这里可以这样使用:
1 | // 字符串固定长度 8位,若不足,往左补 0 |
另外还有一个 StringUtils#rightPad
, 这个方法与上面方法正好相反。
字符串关键字替换
StringUtils
提供一些列的方法,可以替换某些关键字:
1 | // 默认替换所有关键字 |
字符串拼接
字符串拼接是个常见的需求,简单办法使用 StringBuilder
循环遍历拼接:
1 | String[] array = new String[]{"test", "1234", "5678"}; |
上面业务代码不太难,但是需要注意一下上面这段代码非常容易出错,容易抛出 StringIndexOutOfBoundsException
。
这里我们可以直接使用以下方法获取拼接之后字符串:
1 | StringUtils.join(["a", "b", "c"], ",") = "a,b,c" |
StringUtils
只能传入数组拼接字符串,不过我比较喜欢集合拼接,所以再推荐下 Guava 的 Joiner
。
实例代码如下:
1 | String[] array = new String[]{"test", "1234", "5678"}; |
字符串拆分
有字符串拼接,就会有拆分字符串的需求,同样的 StringUtils
也有拆分字符串的方法。
1 | StringUtils.split("a..b.c", '.') = ["a", "b", "c"] |
ps: 注意以上两个方法区别。
StringUtils
拆分之后得到是一个数组,我们可以使用 Guava 的
1 | Splitter splitter = Splitter.on(","); |
StringUtils
内部还有其他常用的方法,小伙伴可以自行查看其 API。
日期相关工具类
DateUtils/DateFormatUtils
JDK8 之前,Java 只提供一个 Date
类,平常我们需要将 Date
按照一定格式转化成字符串,我们需要使用 SimpleDateFormat
。
1 | SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
代码虽然简单,但是这里需要注意 SimpleDateFormat
,不是线程安全的,多线程环境一定要注意使用安全。
这里阿粉推荐 commons-lang3 下的时间工具类DateUtils/DateFormatUtils
, 解决 Date 与字符串转化问题。
ps: 吐槽一下,你们工程中有没有多个叫
DateUtils
类?阿粉发现我们现有工程,多个模块有提供这个类,每个实现大同小异。
使用方法非常简单:
1 | // Date 转化为字符串 |
除了格式转化之外,DateUtils
还提供时间计算的相关功能。
1 | Date now = new Date(); |
JDK8 时间类
JDK8 之后,Java 将日期与时间分为 LocalDate
,LocalTime
,功能定义更加清晰,当然其也提供一个 LocalDateTime
,包含日期与时间。这些类相对于 Date 类优点在于,这些类与 String
类一样都是不变类型,不但线程安全,而且不能修改。
ps:仔细对比 mysql 时间日期类型
DATE
,TIME
,DATETIME
,有没有感觉差不多
现在 mybatis 等 ORM 框架已经支持 LocalDate
与 JDBC 时间类型转化,所以大家可以直接将时间字段实际类型定义为 JDK8 时间类型,然后再进行相关转化。
如果依然使用的是 Date 类型,如果需要使用新的时间类型,我们需要进行相关转化。两者之间进行转化, 稍微复杂一点,我们需要显示指定当前时区。
1 | Date now = new Date(); |
接下来我们使用 LocalDateTime
进行字符串格式化。
1 | // 按照 yyyy-MM-dd HH:mm:ss 转化时间 |
另外我们使用 LocalDateTime
获取当前时间年份,月份特别简单:
1 | LocalDateTime now = LocalDateTime.now(); |
最后我们还可以使用 LocalDateTime
进行日期加减,获取下一天的时间:
1 | LocalDateTime now = LocalDateTime.now(); |
总之 JDK8 提供的时间类非常好用,还没用过小伙伴,可以尝试下。
集合 / 数组相关
集合与数组我们日常也需要经常使用,也需要对其进行判空:
1 | if (null == list || list.isEmpty()) { |
ps: 数组、Map 集合与其类似
上面代码如字符串判空一样写起来都非常简单,但是也比较容易写出会抛出空指针异常的代码。这里我们可以使用 commons-collections 提供工具类。
pom 信息:
1 | <dependency> |
ps: 还有一个低版本的 ,artifactId 为 commons-collections
我们可以使用 CollectionUtils/MapUtils
进行判空判断。
1 | // List/Set 集合判空 |
至于数组判空判断需要使用 commons-lang
下的 ArrayUtils
进行判断:
1 | // 数组判空 |
除此之外还有一些列的对于集合增强方法,比如快速将数组加入到现有集合中:
1 | List<String> listA = new ArrayList<>(); |
其他方法感兴趣同学可以再自行研究下,另外 Guava 中也有提供对于集合的操作增强类 Lists/Maps
, 这个可以看下阿粉之前写的:老司机阿粉带你玩转 Guava 集合类。
I/O 相关
JDK 有提供一系列的类可以读取文件等,不过阿粉觉得那些类有些晦涩难懂,实现一个小功能可能还要写好多代码,而且还不一定能写对。
阿粉推荐一下 Apache 提供的 commons-io
库,增强 I/O 操作,简化操作难度。pom 信息:
1 | <dependency> |
FileUtils - 文件操作工具类
文件操作工具类提供一系列方法,可以让我们快速读取写入文件。
快速实现文件 / 文件夹拷贝操作 ,FileUtils.copyDirectory/FileUtils.copyFile
1 | // 拷贝文件 |
使用 FileUtils.listFiles
获取指定文件夹上所有文件
1 | // 按照指定文件后缀如java,txt等去查找指定文件夹的文件 |
使用 FileUtils.readLines
读取该文件所有行。
1 | // 读取指定文件所有行 不需要使用 while 循环读取流了 |
有读就存在写,可以使用 FileUtils.writeLines
,直接将集合中数据,一行行写入文本。
1 | // 可以一行行写入文本 |
IOUtils-I/O 操作相关工具类
FileUtils
主要针对相关文件操作,IOUtils
更加针对底层 I/O, 可以快速读取 InputStream
。实际上 FileUtils
底层操作依赖就是 IOUtils
。
IOUtils
可以适用于一个比较试用的场景,比如支付场景下,HTTP 异步通知场景。如果我们使用 JDK 原生方法写:
从 Servlet 获取异步通知内容
1 | byte[] b = null; |
上面代码说起来还是挺复杂的。不过我们使用 IOUtils
,一个方法就可以简单搞定:
1 | // 将输入流信息全部输出到字节数组中 |
ps: InputStream 不能被重复读取
计时
编程中有时需要统计代码的的执行耗时,当然执行代码非常简单,结束时间与开始时间相减即可。
1 | long start = System.currentTimeMillis(); //获取开始时间 |
虽然代码很简单,但是非常不灵活,默认情况我们只能获取 ms 单位,如果需要转换为秒,分钟,就需要另外再计算。
这里我们介绍 Guava Stopwatch
计时工具类,借助他统计程序执行时间,使用方式非常灵活。
commons-lang3 与 Spring-core 也有这个工具类,使用方式大同小异,大家根据情况选择。
1 | // 创建之后立刻计时,若想主动开始计时 |
输出结果为:
总结
今天阿粉抛砖引玉,介绍了字符串、日期、数组 / 集合、I/O、计时等工具类,简化日常业务代码。大家看完可以尝试一下,不得不说,这些工具类真香!
如果大家喜欢我们的文章,欢迎大家转发,点击在看让更多的人看到。也欢迎大家热爱技术和学习的朋友加入的我们的知识星球当中,我们共同成长,进步。
往期精彩回顾