百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

求求你了,不要再自己实现这些逻辑了,开源工具类不香吗

toyiye 2024-05-25 20:11 19 浏览 0 评论

前言

最近项目不是很忙,空闲的时候会去 Review 其他同事写的代码,发现有些代码逻辑有些繁琐,其实可以用一些开源工具类实现,不需要重复处理。想当初自己也是这么过来的,只是现在慢慢的更加注重效率了,通过逐渐积累。现在写代码才会直接用工具类替换自己实现的这些繁琐的逻辑。大家有需要的可以看看哦!


下文主要分享这几个方向的常用工具类:

字符串相关工具类

Java 中 String 应该是日常用的最多一个类吧,平常我们很多代码需要围绕 String ,做一些处理。 JDK 提供 String,API 虽然比较多,但是功能比较基础,通常我们需要结合 String 多个方法才能完成一个业务功能。 下面介绍一下 Apache提供的一个工具类 StringUtils. Maven Pom 信息如下:

<dependency>

<groupId>org.apache.commons</groupId>

<artifactId>commons-lang3</artifactId>

<version>3.10</version>

</dependency>

commons-lang 有两个版本,一个是 commons-lang3 ,一个是 commons-lang 。

commons-lang 是老版本,已经很久没有维护了。

commons-lang3 是一直在维护的版本,推荐直接使用这个版本。

1.判断字符串是否为空

判断字符串是否为空,想必每个人应该都写过吧:

if (null == str || str.isEmpty()) {

}

虽然这段代码非常简单,但是说实话,我以前还是在这里犯过空指针的异常的。

使用 StringUtils ,上面代码可以替换下面这样:

if (StringUtils.isEmpty(str)) {

}

StringUtils 内部还有一个方法 isBlank,也是用来判断字符串是否为空,两个方法比较相近,比较搞混,主要区别如下:

// 如果字符串都是空格的话,

StringUtils.isBlank(" ") = true;

StringUtils.isEmpty(" ") = false;

2.字符串固定长度

这个通常用于字符串需要固定长度的场景,比如需要固定长度字符串作为流水号,若流水号长度不足,,左边补 0 。这里当然可以使用 String#format 方法,不过我觉得比较麻烦,这里可以这样使用:

// 字符串固定长度 8位,若不足,往左补 0

StringUtils.leftPad("test", 8, "0");

另外还有一个 StringUtils#rightPad,这个方法与上面方法正好相反。

3.字符串关键字替换

StringUtils 提供一些列的方法,可以替换某些关键字:

// 默认替换所有关键字

StringUtils.replace("aba", "a", "z") = "zbz";

// 替换关键字,仅替换一次

StringUtils.replaceOnce("aba", "a", "z") = "zba";

// 使用正则表达式替换

StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "") = "ABC123";

....

4.字符串拼接

字符串拼接是个常见的需求,简单办法使用 StringBuilder 循环遍历拼接:

String[] array = new String[]{"test", "1234", "5678"};

StringBuilder stringBuilder = new StringBuilder();

for (String s : array) {

stringBuilder.append(s).append(";");

}

// 防止最终拼接字符串为空

if (stringBuilder.length() > 0) {

stringBuilder.deleteCharAt(stringBuilder.length() - 1);

}

System.out.println(stringBuilder.toString());

上面业务代码不太难,但是需要注意一下上面这段代码非常容易出错,容易抛出 StringIndexOutOfBoundsException。

这里我们可以直接使用以下方法获取拼接之后字符串:

StringUtils.join(["a", "b", "c"], ",") = "a,b,c"

StringUtils 只能传入数组拼接字符串,不过我比较喜欢集合拼接,所以再推荐下 Joiner。

实例代码如下:

String[] array = new String[]{"test", "1234", "5678"};

List<String> list=new ArrayList<>();

list.add("test");

list.add("1234");

list.add("5678");

StringUtils.join(array, ",");

// 逗号分隔符,跳过 null

Joiner joiner=Joiner.on(",").skipNulls();

joiner.join(array);

joiner.join(list);

5.字符串拆分

有字符串拼接,就会有拆分字符串的需求,同样的 StringUtils 也有拆分字符串的方法。

StringUtils.split("a..b.c", '.') = ["a", "b", "c"]

StringUtils.splitByWholeSeparatorPreserveAllTokens("a..b.c", ".")= ["a","", "b", "c"]

StringUtils 拆分之后得到是一个数组,我们可以使用 Guava 的

Splitter splitter = Splitter.on(",");

// 返回是一个 List 集合,结果:[ab, , b, c]

splitter.splitToList("ab,,b,c");

// 忽略空字符串,输出结果 [ab, b, c]

splitter.omitEmptyStrings().splitToList("ab,,b,c")

StringUtils 内部还有其他常用的方法,小伙伴可以自行查看其 API。

日期相关工具类

1.DateUtils/DateFormatUtils

JDK8 之前,Java 只提供一个 Date 类,平常我们需要将 Date 按照一定格式转化成字符串,我们需要使用 SimpleDateFormat。

SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

// Date 转 字符串

simpleDateFormat.format(new Date());

// 字符串 转 Date

simpleDateFormat.parse("2020-05-07 22:00:00");

代码虽然简单,但是这里需要注意 SimpleDateFormat,不是线程安全的,多线程环境一定要注意使用安全。

这里我推荐 commons-lang3 下的时间工具类DateUtils/DateFormatUtils,解决 Date 与字符串转化问题。

ps:吐槽一下,你们工程中有没有多个叫 DateUtils 类?我发现我们现有工程,多个模块有提供这个类,每个实现大同小异。

使用方法非常简单:

// Date 转化为字符串

DateFormatUtils.format(new Date(),"yyyy-MM-dd HH:mm:ss");

// 字符串 转 Date

DateUtils.parseDate("2020-05-07 22:00:00","yyyy-MM-dd HH:mm:ss");

除了格式转化之外,DateUtils 还提供时间计算的相关功能。

Date now = new Date();

// Date 加 1 天

Date addDays = DateUtils.addDays(now, 1);

// Date 加 33 分钟

Date addMinutes = DateUtils.addMinutes(now, 33);

// Date 减去 233 秒

Date addSeconds = DateUtils.addSeconds(now, -233);

// 判断是否 Wie 同一天

boolean sameDay = DateUtils.isSameDay(addDays, addMinutes);

// 过滤时分秒,若 now 为 2020-05-07 22:13:00 调用 truncate 方法以后

// 返回时间为 2020-05-07 00:00:00

Date truncate = DateUtils.truncate(now, Calendar.DATE);

2.JDK8 时间类

JDK8 之后,Java 将日期与时间分为 LocalDate,LocalTime,功能定义更加清晰,当然其也提供一个 LocalDateTime,包含日期与时间。这些类相对于 Date 类优点在于,这些类与 String 类一样都是不变类型,不但线程安全,而且不能修改。

ps:仔细对比 mysql 时间日期类型 DATE,TIME,DATETIME,有没有感觉差不多

现在 mybatis 等 ORM 框架已经支持 LocalDate 与 JDBC 时间类型转化,所以大家可以直接将时间字段实际类型定义为 JDK8 时间类型,然后再进行相关转化。

如果依然使用的是 Date 类型,如果需要使用新的时间类型,我们需要进行相关转化。两者之间进行转化, 稍微复杂一点,我们需要显示指定当前时区。

Date now = new Date();

// Date-----> LocalDateTime 这里指定使用当前系统默认时区

LocalDateTime localDateTime = now.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();

// LocalDateTime------> Date 这里指定使用当前系统默认时区

Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());

接下来我们使用 LocalDateTime 进行字符串格式化。

// 按照 yyyy-MM-dd HH:mm:ss 转化时间

LocalDateTime dateTime = LocalDateTime.parse("2020-05-07 22:34:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

// 将 LocalDateTime 格式化字符串

String format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(dateTime);

另外我们使用 LocalDateTime 获取当前时间年份,月份特别简单:

LocalDateTime now = LocalDateTime.now();

// 年

int year = now.getYear();

// 月

int month = now.getMonthValue();

// 日

int day = now.getDayOfMonth();

最后我们还可以使用 LocalDateTime 进行日期加减,获取下一天的时间:

LocalDateTime now = LocalDateTime.now();

// 当前时间加一天

LocalDateTime plusDays = now.plusDays(1l);

// 当前时间减一个小时

LocalDateTime minusHours = now.minusHours(1l);

// 还有很多其他方法

总之 JDK8 提供的时间类非常好用,还没用过小伙伴,可以尝试下。

集合/数组相关

集合与数组我们日常也需要经常使用,也需要对其进行判空:

if (null == list || list.isEmpty()) {

}

上面代码如字符串判空一样写起来都非常简单,但是也比较容易写出会抛出空指针异常的代码。这里我们可以使用 commons-collections 提供工具类。

<dependency>

<groupId>org.apache.commons</groupId>

<artifactId>commons-collections4</artifactId>

<version>4.4</vesion>

</dependency>

我们可以使用 CollectionUtils/MapUtils进行判空判断。

// List/Set 集合判空

if(CollectionUtils.isEmpty(list)){

}

// Map 等集合进行判空

if (MapUtils.isEmpty(map)) {

}

至于数组判空判断需要使用 commons-lang 下的 ArrayUtils进行判断:

// 数组判空

if (ArrayUtils.isEmpty(array)) {

}

除此之外还有一些列的对于集合增强方法,比如快速将数组加入到现有集合中:

List<String> listA = new ArrayList<>();

listA.add("1");

listA.add("2");

listA.add("3");

String[] arrays = new String[]{"a", "b", "c"};

CollectionUtils.addAll(listA, arrays);

其他方法感兴趣的小伙伴可以再自行研究下。

I/O 相关

JDK 有提供一系列的类可以读取文件等,不过我觉得那些类有些晦涩难懂,实现一个小功能可能还要写好多代码,而且还不一定能写对。

推荐一下 Apache 提供的 commons-io 库,增强 I/O 操作,简化操作难度。pom 信息:

<dependency>

<groupId>commons-io</groupId>

<artifactId>commons-io</artifactId>

<version>2.6</version>

</dependency>

1.FileUtils-文件操作工具类

文件操作工具类提供一系列方法,可以让我们快速读取写入文件。

快速实现文件/文件夹拷贝操作 ,FileUtils.copyDirectory/FileUtils.copyFile

// 拷贝文件

File fileA = new File("E:\\test\\test.txt");

File fileB = new File("E:\\test1\\test.txt");

FileUtils.copyFile(fileA,fileB);

使用 FileUtils.listFiles 获取指定文件夹上所有文件

// 按照指定文件后缀如java,txt等去查找指定文件夹的文件

File directory = new File("E:\\test");

FileUtils.listFiles(directory, new String[]{"txt"}, false);

使用 FileUtils.readLines 读取该文件所有行。

// 读取指定文件所有行 不需要使用 while 循环读取流了

List<String> lines = FileUtils.readLines(fileA)

有读就存在写,可以使用 FileUtils.writeLines,直接将集合中数据,一行行写入文本。

// 可以一行行写入文本

List<String> lines = new ArrayList<>();

.....

FileUtils.writeLines(lines)

2.IOUtils-I/O 操作相关工具类

FileUtils 主要针对相关文件操作,IOUtils 更加针对底层 I/O,可以快速读取 InputStream。实际上 FileUtils 底层操作依赖就是 IOUtils。

IOUtils可以适用于一个比较试用的场景,比如支付场景下,HTTP 异步通知场景。如果我们使用 JDK 原生方法写:

byte[] b = null;

ByteArrayOutputStream baos = null;

String respMsg = null;

try {

byte[] buffer = new byte[1024];

baos = new ByteArrayOutputStream();

// 获取输入流

InputStream in = request.getInputStream();

for (int len = 0; (len = in.read(buffer)) > 0; ) {

baos.write(buffer, 0, len);

}

b = baos.toByteArray();

baos.close();

// 字节数组转化成字符串

String reqMessage = new String(b, "utf-8");

} catch (IOException e) {

} finally {

if (baos != null) {

try {

baos.close();

} catch (IOException e) {

}

}

}

上面代码说起来还是挺复杂的。不过我们使用 IOUtils,一个方法就可以简单搞定:

// 将输入流信息全部输出到字节数组中

byte[] b = IOUtils.toByteArray(request.getInputStream());

// 将输入流信息转化为字符串

String resMsg = IOUtils.toString(request.getInputStream());

ps: InputStream 不能被重复读取

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码