- Gitee 地址:hutool: 🍬小而全的Java工具类库,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。 (gitee.com)【gitee.com/dromara/hut…】
- Hutool 官网地址:Hutool — 🍬A set of tools that keep Java sweet.【hutool.cn/】
- Hutool 中文文档地址:
-- 正常地址:入门和安装 (hutool.cn)【hutool.cn/docs/#/】
-- 备份地址:入门和安装 (hutool.cn)【plus.hutool.cn/docs/#/】
一、简单介绍
(1)简要概述
- Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。
- Hutool中的工具方法来自每个用户的精雕细琢,它涵盖了Java开发底层代码中的方方面面,它既是大型项目开发中解决小问题的利器,也是小型项目中的效率担当;
- Hutool是项目中 “util”包友好的替代,它节省了开发人员对项目中公用类和公用工具方法的封装时间,使开发专注于业务,同时可以最大限度的避免封装不完善带来的bug。
(2)核心组件
① hutool模块介绍
模块 | 介绍 |
---|---|
hutool-aop | JDK动态代理封装,提供非IOC下的切面支持 |
hutool-bloomFilter | 布隆过滤,提供一些Hash算法的布隆过滤 |
hutool-cache | 简单缓存实现 |
hutool-core | 核心,包括Bean操作、日期、各种Util等 |
hutool-cron | 定时任务模块,提供类Crontab表达式的定时任务 |
hutool-crypto | 加密解密模块,提供对称、非对称和摘要算法封装 |
hutool-db | JDBC封装后的数据操作,基于ActiveRecord思想 |
hutool-dfa | 基于DFA模型的多关键字查找 |
hutool-extra | 扩展模块,对第三方封装(模板引擎、邮件、Servlet、二维码、Emoji、FTP、分词等) |
hutool-http | 基于HttpUrlConnection的Http客户端封装 |
hutool-log | 自动识别日志实现的日志门面 |
hutool-script | 脚本执行封装,例如Javascript |
hutool-setting | 功能更强大的Setting配置文件和Properties封装 |
hutool-system | 系统参数调用封装(JVM信息等) |
hutool-json | JSON实现 |
hutool-captcha | 图片验证码实现 |
hutool-poi | 针对POI中Excel和Word的封装 |
hutool-socket | 基于Java的NIO和AIO的Socket封装 |
hutool-jwt | JSON Web Token (JWT)封装实现 |
🌹 温馨提示:以根据需求对每个模块单独引入,也可以通过引入【hutool-all】方式引入所有模块。
② 常用核心处理类
工具类 | 解释说明 |
---|---|
DateUtil | 日期时间工具类(DateTime 日期时间对象) |
ChineseDate | 农历日期 |
LocalDateTimeUtil | 本地日期时间工具类(JDK8) |
TimeInterval | 计时器工具类(可以计算方法或过程执行的时间。支持分组计时,方便对比时间。) |
IoUtil.java | IO流工具类,主要针对InputStream、OutputStream、Reader、Writer封装简化,并对NIO相关操作做封装简化。总体来说,Hutool对IO的封装,主要是工具层面,我们努力做到在便捷、性能和灵活之间找到最好的平衡点。 |
二、入门安装使用
(1)引入依赖
① maven 方式
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.4</version>
</dependency>
② gradle 方式
implementation 'cn.hutool:hutool-all:5.8.4'
③ 直接下载 JAR 方式
(2)使用示例
部分核心功能演示:
① 对象克隆
- 泛型克隆:① 实体类实现 Cloneable<T>; ② 对象调用clone方法;③ 见 testHutoolClone();
- 泛型克隆:① 实体类集成 CloneSupport<T>; ② 对象调用clone方法;③ 见 testHutoolClone2();
- 深拷贝(工具类深拷贝):① 实体类实现序列化;②直接使用 ObjectUtil.cloneByStream(obj); ② 见 testHutoolClone3();
import cn.hutool.core.clone.CloneRuntimeException;
import cn.hutool.core.clone.CloneSupport;
import cn.hutool.core.clone.Cloneable;
import cn.hutool.core.util.ObjectUtil;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
* Hutool 工具部分功能示例
* <pre>
* 1.克隆功能
* 1.1 泛型克隆:① 实体类实现 Cloneable<T>; ② 对象调用clone方法;③ 见 testHutoolClone()
* 1.2 泛型克隆:① 实体类集成 CloneSupport<T>; ② 对象调用clone方法;③ 见 testHutoolClone2()
* 1.3 深拷贝(工具类深拷贝):① 实体类实现序列化;②直接使用 ObjectUtil.cloneByStream(obj); ② 见 testHutoolClone3()
* 2.
* </pre>
* @author zl
* @date 2022-07-01 15:37
*/
public class HutoolDemo {
public static void main(String[] args) {
System.out.println("==============hutool 5.8.4=============");
//testHutoolClone();
//testHutoolClone2();
testHutoolClone3();
}
private static void testHutoolClone() {
// 初始对象
UserEntity userEntity = UserEntity.builder().id(1).name("Drew").birthday(new Date()).build();
// 克隆对象()
UserEntity clone = userEntity.clone();
// 修改克隆对象,判断是否深度克隆
clone.setName("Mark");
System.out.println("初始对象:" + userEntity);
System.out.println("克隆对象(修改):" + clone);
}
private static void testHutoolClone2() {
UserEntity2 userEntity2 = UserEntity2.builder().userId(2).userName("Bob").build();
UserEntity2 clone2 = userEntity2.clone();
clone2.setUserName("Baby");
System.out.println("初始对象:" + userEntity2);
System.out.println("克隆对象(修改):" + clone2);
}
private static void testHutoolClone3() {
User user = User.builder().id(3).name("King").build();
// 简化的克隆方法为 ObjectUtil.clone(obj) 也可
User userClone = ObjectUtil.cloneByStream(user);
userClone.setName("KingKong");
System.out.println("初始对象:" + user);
System.out.println("克隆对象(修改):" + userClone);
}
}
@Data
@Builder
class UserEntity implements Cloneable<UserEntity> {
private Integer id;
private String name;
private Date birthday;
@Override
public UserEntity clone() {
try {
return (UserEntity) super.clone();
} catch (CloneNotSupportedException e) {
throw new CloneRuntimeException(e);
}
}
}
@Data
@Builder
@EqualsAndHashCode(callSuper = true)
class UserEntity2 extends CloneSupport<UserEntity2> {
private Integer userId;
private String userName;
}
@Data
@Builder
class User implements Serializable {
private Integer id;
private String name;
}
② 数据类型转换
- 转字符串;
- 转日期;
- 转集合;
- 泛型转换成指定类型;
- 其他业务特殊需要转换;
package com.base.utils.docx;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.lang.hash.Number128;
import cn.hutool.core.util.CharsetUtil;
import lombok.Builder;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* Hutool 数据类型转换
* <pre>
* 1.转字符串;
* 2.转日期;
* 3.转集合;
* 4.泛型转指定类型;(重点)
* 5.其他转换;(重点)
* </pre>
*
* @author zl
* @date 2022-07-01 15:37
*/
public class HutoolDemo {
public static void main(String[] args) {
// 转字符串
//testConvert();
// 转日期
//testConvertToDate();
// 转集合
//testConvertToList();
// map转对象(重点)
//testConvertMapToObj();
// 泛型类型转换(重点)
//testConvertTypeObj();
// 其他转换(半角→全角、16进制、unicode→字符串、编码转换、金额大小写转换、时间单位转换、数字转换)
testConvertOther();
}
private static void testConvertOther() {
// 1.半角 → 全角 (//结果为:"123456789")
String sbc = Convert.toSBC("123456789");
System.out.println("半角 → 全角: " + sbc);
// 1.2 全角 → 半角("123456789")
String dbc = Convert.toDBC("123456789");
System.out.println("全角 → 半角: " + dbc);
// 2.1 字符串→ 16进制字符
//结果:"e68891e698afe4b880e4b8aae5b08fe5b08fe79a84e58fafe788b1e79a84e5ad97e7aca6e4b8b2"
System.out.println("字符串→ 16进制字符: " + Convert.toHex("我是一个小小的可爱的字符串", CharsetUtil.CHARSET_UTF_8));
// 2.2 16进制 → 字符串
String hex = "e68891e698afe4b880e4b8aae5b08fe5b08fe79a84e58fafe788b1e79a84e5ad97e7aca6e4b8b2";
//结果为:"我是一个小小的可爱的字符串"(注意:在4.1.11之后hexStrToStr将改名为hexToStr)
System.out.println("16进制 → 字符串: " + Convert.hexToStr(hex, CharsetUtil.CHARSET_UTF_8));
// 3.1 unicode → 字符串
//结果为:"\\u6211\\u662f\\u4e00\\u4e2a\\u5c0f\\u5c0f\\u7684\\u53ef\\u7231\\u7684\\u5b57\\u7b26\\u4e32"
String unicode = Convert.strToUnicode("我是一个小小的可爱的字符串");
System.out.println("字符串 → unicode:" + unicode);
//结果为:"我是一个小小的可爱的字符串"
System.out.println("unicode → 字符串:" + Convert.unicodeToStr(unicode));
// 4.编码转换(注意 经过测试,UTF-8编码后用GBK解码再用GBK编码后用UTF-8解码会存在某些中文转换失败的问题。)
// 4.1 UTF-8 👉 ISO_8859_1
String a = "我不是乱码";
//转换后result为乱码
String result = Convert.convertCharset(a, CharsetUtil.UTF_8, CharsetUtil.ISO_8859_1);
String raw = Convert.convertCharset(result, CharsetUtil.ISO_8859_1, "UTF-8");
System.out.println("编码转换:" + Objects.equals(raw, a));
// 5.时间单位转换
// 5.1 微秒 👉 分钟 (结果:75)
System.out.println("时间单位转换:" + Convert.convertTime(4535345, TimeUnit.MILLISECONDS, TimeUnit.MINUTES));
// 6.金额大小写转换(注意 转换为大写只能精确到分(小数点儿后两位),之后的数字会被忽略。)
// 结果为:"陆万柒仟伍佰伍拾陆元叁角贰分"
System.out.println("两位小数数据转金额大写:" + Convert.digitToChinese(67556.32));
// 7.数字转换
// 7.1 数字转英文表达
// 结果:ONE HUNDRED AND TWENTY AND CENTS TWENTY THREE ONLY
System.out.println("数字转英文表达(>1):" + Convert.numberToWord(120.23));
// 结果:AND CENTS ONE ONLY
System.out.println("数字转英文表达(<1):" + Convert.numberToWord(0.01));
// 7.2 数字简化
System.out.println("数字简化(12000👉1.2w):" + Convert.numberToSimple(12000)); // 1.2w
// 7.3 数字转中文
// 一万零八百八十九点七二
System.out.println("数字转中文:" + Convert.numberToChinese(10889.72356, false));
// 壹万贰仟陆佰伍拾叁
System.out.println("金额大写:" + Convert.numberToChinese(12653, true));
// 7.4 数字中文表示转换为数字
System.out.println("数字中文表示转换为数字: " + Convert.chineseToNumber("一千零八十二"));// 1082
// 8.原始类和包装类转换
//去包装(结果为:int.class)
Class<?> unWraped = Convert.unWrap(Integer.class);
//包装(结果为:Long.class)
Class<?> wraped = Convert.wrap(long.class);
System.out.println(unWraped + " ------ " + wraped);
}
/**
* 将复合类型的数组转换成指定同一类型的集合
*/
private static void testConvertTypeObj() {
Object[] a = {"a", "你", "好", "", 1, true, null, Collections.emptyList(), Collections.emptyMap()};
List<String> list = Convert.convert(new TypeReference<List<String>>() {
}, a);
System.out.println("复合类型集合转指定类型集合:" + list);
}
/**
* 通过Convert.convert(Class<T>, Object)方法可以将任意类型转换为指定类型
*/
private static void testConvertMapToObj() {
Map<String, Object> userMap = new HashMap<>(2);
userMap.put("id", 1);
userMap.put("name", "Halen");
userMap.put("remark", "此map-key不存在于 user属性上,判断是否能赚成功?丢失映射,映射失败");
User user = Convert.convert(User.class, userMap);
System.out.println("map 👉 obj" + user);
}
private static void testConvertToTypeArr() {
//结果为Integer数组
Integer[] intArray = Convert.toIntArray(new String[]{"1", "2", "3", "4"});
//结果为Integer数组
Integer[] intArray2 = Convert.toIntArray(new Integer[]{1, 2, 3, 4, 5});
}
private static void testConvertToList() {
// 1.纯数字数组转集合 [1, 2, 3, 4]
System.out.println("数字数组 👉 集合:" + Convert.toList(new Integer[]{1, 2, 3, 4}));
// 2.纯字符数组转集合 [one, two, three]
System.out.println("字符数组 👉 集合:" + Convert.toList(new String[]{"one", "two", "three"}));
// 3.对象数组转集合 [true, null, [], 1, {}, hi]
System.out.println("复合集合 👉 集合:" + Convert.toList(new Object[]{true, null, Collections.emptyList(), 1, new HashMap<>(1), "hi"}));
// 方法二:List<?> list = Convert.convert(List.class, a);
}
private static void testConvertToDate() {
System.out.println("==============hutool 5.8.4 转日期=============");
// 1.日期字符串转日期
System.out.println("日期字符串 → 日期:" + Convert.toDate("2017-05-06"));
// 1.1 如果字符串日期不符合日期格式,则使用默认日期进行处理
System.out.println("转日期(转换异常使用默认值):" + Convert.toDate("2022-07-01 10:10:100", new Date()));
// 2.date 转 localDateTime
System.out.println("date 👉 localDateTime:" + Convert.toLocalDateTime(new Date()));
// 2.1 date转localDateTime,带默认值
System.out.println("date 👉 localDateTime(转换异常使用默认值):" + Convert.toLocalDateTime(new Date(), LocalDateTime.now()));
// 3.转 LocalDateTime
// 3.1 字符串转 LocalDateTime
System.out.println("字符串 👉 localDatetime: " + Convert.toLocalDateTime("2017-05-06"));
// 3.2 字符串转 LocalDateTime(转换异常使用默认值)
System.out.println("字符串 👉 localDatetime(转换异常使用默认值): " + Convert.toLocalDateTime("2017-05-06 10:20:30", LocalDateTime.now()));
}
private static void testConvert() {
System.out.println("==============hutool 5.8.4 转字符串=============");
// 1.数字转字符串
int num = 100_000;
// 100000
System.out.println("数字转字符串:" + Convert.toStr(num));
// 2.数组转字符串
int[] numArr = {1, 2, 3, 4, 5};
// "[1, 2, 3, 4, 5]"
System.out.println("数字数组转字符串:" + Convert.toStr(numArr));
// "[1, 2, 3, 4, 5]"
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
System.out.println("list集合转字符串:" + Convert.toStr(integerList));
List<Object> objectList = Arrays.asList(null, true, "str", 0, new Arrays[]{}, 1, new HashMap<>(1));
// "[null, true, str, 0, [Ljava.util.Arrays;@71e7a66b, 1, {}]"
System.out.println("复合对象集合转字符串:" + Convert.toStr(objectList));
// 3.map集合转字符串数组(set类似)
Map<String, Integer> map1 = new HashMap<>(2);
map1.put("one", 1);
map1.put("two", 2);
// "{two=2, one=1}"
System.out.println("map转字符串:" + Convert.toStr(map1));
}
}
@Data
@Builder
class User implements Serializable {
private Integer id;
private String name;
}
温馨提示:可以自定义转换策略的接口(ConverterRegistry)。
③ 日期时间
- Date、long、Calendar之间的相互转换;
- 字符串转日期;
- 格式化日期输出;
- 获取Date对象的某个部分;
- 开始和结束时间;
- 日期时间偏移;
- 日期时间差;
- 格式化时间差;
- 星座和属相;
- 其它;
//当前时间
Date date = DateUtil.date();
//当前时间
Date date2 = DateUtil.date(Calendar.getInstance());
//当前时间
Date date3 = DateUtil.date(System.currentTimeMillis());
//当前时间字符串,格式:yyyy-MM-dd HH:mm:ss
String now = DateUtil.now();
//当前日期字符串,格式:yyyy-MM-dd
String today= DateUtil.today();
【1】字符转日期
DateUtil.parse方法会自动识别一些常用格式,包括:
- yyyy-MM-dd HH:mm:ss
- yyyy/MM/dd HH:mm:ss
- yyyy.MM.dd HH:mm:ss
- yyyy年MM月dd日 HH时mm分ss秒
- yyyy-MM-dd
- yyyy/MM/dd
- yyyy.MM.dd
- HH:mm:ss
- HH时mm分ss秒
- yyyy-MM-dd HH:mm
- yyyy-MM-dd HH:mm:ss.SSS
- yyyyMMddHHmmss
- yyyyMMddHHmmssSSS
- yyyyMMdd
- EEE, dd MMM yyyy HH:mm:ss z
- EEE MMM dd HH:mm:ss zzz yyyy
- yyyy-MM-dd'T'HH:mm:ss'Z'
- yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
- yyyy-MM-dd'T'HH:mm:ssZ
- yyyy-MM-dd'T'HH:mm:ss.SSSZ
```java
Date date = DateUtil.parse("2017-03-01");
// 自定义日期格式化
Date date = DateUtil.parse("2017-03-01", "yyyy-MM-dd");
【2】格式化日期输出
Date date = DateUtil.parse("2017-03-01");
//(指定格式)结果 2017/03/01
String format = DateUtil.format(date, "yyyy/MM/dd");
//(默认格式)常用格式的格式化,结果:2017-03-01
String formatDate = DateUtil.formatDate(date);
//(自动格式化:年月日时分秒)结果:2017-03-01 00:00:00
String formatDateTime = DateUtil.formatDateTime(date);
//(自动格式化:时分秒)结果:00:00:00
String formatTime = DateUtil.formatTime(date);
【3】获取Date对象某个部分
Date date = DateUtil.date();
//获得【年的部分】
DateUtil.year(date);
//获得【月份,从0开始计数】
DateUtil.month(date);
//获得【月份枚举】
DateUtil.monthEnum(date);
【4】获取开始和结束时间
Date date = DateUtil.parse("2017-03-01 22:33:23");
//一天的开始,结果:2017-03-01 00:00:00
Date beginOfDay = DateUtil.beginOfDay(date);
//一天的结束,结果:2017-03-01 23:59:59
Date endOfDay = DateUtil.endOfDay(date);
【5】日期时间转移
日期或时间的偏移指针对某个日期增加或减少分、小时、天等等,达到日期变更的目的。Hutool也针对其做了大量封装
Date date = DateUtil.parse("2017-03-01 22:33:23");
//通用:(之后第三天)结果:2017-03-03 22:33:23
Date newDate = DateUtil.offset(date, DateField.DAY_OF_MONTH, 2);
//1.常用偏移(增加三天),结果:2017-03-04 22:33:23
DateTime newDate2 = DateUtil.offsetDay(date, 3);
//2.常用偏移(前三个小时的日期),结果:2017-03-01 19:33:23
DateTime newDate3 = DateUtil.offsetHour(date, -3);` </pre>
针对当前时间,提供了简化的偏移方法(例如昨天、上周、上个月等):
public static void main(String[] args) {
//当前日期为:2022-07-01 21:41:12(2022-07-01)
System.out.println("当前日期为:" + DateUtil.date() + "(" + DateUtil.today() + ")");
//昨天日期为:2022-06-30 21:41:12
System.out.println("昨天日期为:" + DateUtil.yesterday());
//明天日期为:2022-07-02 21:41:12
System.out.println("明天日期为:" + DateUtil.tomorrow());
//上周星期日期为:2022-06-24 21:41:12
System.out.println("上周星期日期为:" + DateUtil.lastWeek());
//下周星期日期为:2022-07-08 21:41:12
System.out.println("下周星期日期为:" + DateUtil.nextWeek());
//上月当前日期为:2022-06-01 21:41:12
System.out.println("上月当前日期为:" + DateUtil.lastMonth());
//下月当前日期为:2022-08-01 21:41:12
System.out.println("下月当前日期为:" + DateUtil.nextMonth());
// JDK8 的 LocalDate 日期工具类
//昨天
String yesterdayStr = LocalDate.now().minusDays(1).atStartOfDay().atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println("yesterdayStr = " + yesterdayStr);
//今天
String todayStr = LocalDate.now().atStartOfDay().atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println("todayStr = " + todayStr);
//明天
String tomorrowStr = LocalDate.now().plusDays(1).atStartOfDay().atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println("tomorrowStr = " + tomorrowStr);
//上个月
String lastMonthStr = LocalDate.now().minusMonths(1).atStartOfDay().atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println("lastMonthStr = " + lastMonthStr);
//下个月
String nextMonthStr = LocalDate.now().plusMonths(1).atStartOfDay().atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println("nextMonthStr = " + nextMonthStr);
//去年
String lastYearStr = LocalDate.now().minusYears(1).atStartOfDay().atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println("lastYearStr = " + lastYearStr);
//明年
String nextYearStr = LocalDate.now().plusYears(1).atStartOfDay().atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println("nextYearStr = " + nextYearStr);
}
【6】日期时间差
/**
* 有时候我们需要计算两个日期之间的时间差(相差天数、相差小时数等等),Hutool将此类方法封装为【between方法】:
*/
private static void testPeriods() {
// 1.计算天数
Date date1 = DateUtil.parse("2017-03-01 22:33:23");
Date date2 = DateUtil.parse("2017-04-01 23:33:23");
//相差一个月,31天
System.out.println("日期时间差: " + DateUtil.between(date1, date2, DateUnit.DAY));
// 2.计算相隔周数
date1 = DateUtil.parse("2022-07-01");
date2 = DateUtil.parse("2021-07-01");
// 相隔周数:52
System.out.println("相隔周数:" + DateUtil.between(date1, date2, DateUnit.WEEK));
date1 = DateUtil.parse("2022-07-01 10:23:26");
date2 = DateUtil.parse("2022-07-01 12:23:26");
// 相隔小时数:2
System.out.println("相隔小时数:" + DateUtil.between(date1, date2, DateUnit.HOUR));
date1 = DateUtil.parse("2022-07-01 10:00:26");
date2 = DateUtil.parse("2022-07-01 12:23:26");
// 相隔分钟数:143
System.out.println("相隔小时数:" + DateUtil.between(date1, date2, DateUnit.MINUTE));
// 相隔毫秒数:8580000
System.out.println("相隔毫秒数:" + DateUtil.between(date1, date2, DateUnit.MS));
}
【7】格式化时间差
import cn.hutool.core.date.BetweenFormatter;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console;
private static void formartBetween() {
Date date1 = DateUtil.parse("2022-07-01 10:00:26");
Date date2 = DateUtil.parse("2022-07-01 12:23:26");
// 相隔分钟数:8580000
long between = DateUtil.between(date1, date2, DateUnit.MS);
//Level.MINUTE表示精确到分
String formatBetween = DateUtil.formatBetween(between, BetweenFormatter.Level.MINUTE);
// 相隔小时数:8580000(2小时23分)
System.out.println("相隔毫秒数:" + between + "(" + formatBetween + ")");
//输出:2小时23分
Console.log(formatBetween);
}
【8】星座、属相、年龄、平闰年
private static void testZodiac() {
// 1.星座 + 属相
String zodiac = DateUtil.getZodiac(Month.JANUARY.getValue(), 19);
String chineseZodiac = DateUtil.getChineseZodiac(1994);
// 输出 星座:摩羯座(属相:狗)
System.out.println("星座:" + zodiac + "(属相:" + chineseZodiac + ")");
// 2\. 年龄 + 是否闰年
int ageOfNow = DateUtil.ageOfNow("1990-01-30");
int yearNo = 2017;
boolean leapYearFlag = DateUtil.isLeapYear(yearNo);
// 输出 今天年龄:32,2017是否为闰年?false
System.out.println("今天年龄:" + ageOfNow + "," + yearNo + "是否为闰年?" + leapYearFlag);
}
④ 字符串工具(StrUtil.java)
这个工具的用处类似于Apache Commons Lang中的StringUtil,常用的方法例如isBlank、isNotBlank、isEmpty、isNotEmpty。
【1】hasBlank 方法
就是给定一些字符串,如果一旦有空的就返回true,常用于判断好多字段是否有空的(例如web表单数据)。
这两个方法的区别是hasEmpty只判断是否为null或者空字符串(""),hasBlank则会把不可见字符也算做空,isEmpty和isBlank同理。
【2】removePrefix 方法
这两个是去掉字符串的前缀后缀的,例如去个文件名的扩展名啥。
String fileName = StrUtil.removeSuffix("pretty_girl.jpg", ".jpg");
//fileName -> pretty_girl
还有忽略大小写的 removePrefixIgnoreCase 和 removeSuffixIgnoreCase 都比较实用。
【3】sub方法
不得不提一下这个方法,有人说String有了subString你还写它干啥,我想说subString方法越界啥的都会报异常,而使用 StrUtil 的sub就不会报错:
String str = "abcdefgh";
String strSub1 = StrUtil.sub(str, 2, 3); //strSub1 -> c
String strSub2 = StrUtil.sub(str, 2, -3); //strSub2 -> cde
String strSub3 = StrUtil.sub(str, 3, 2); //strSub2 -> c
【4】format方法
灵感来自slf4j,可以使用字符串模板代替字符串拼接。
String template = "{}爱{},就像老鼠爱大米";
String str = StrUtil.format(template, "我", "你"); //str -> 我爱你,就像老鼠爱大米
⑤ IdUtil
在分布式环境中,唯一ID生成应用十分广泛,生成方法也多种多样,Hutool针对一些常用生成策略做了简单封装。
唯一ID生成器的工具类,涵盖了:
- UUID
- ObjectId(MongoDB)
- Snowflake(Twitter)
【1】UUID
UUID全称通用唯一识别码(universally unique identifier),JDK通过java.util.UUID提供了 Leach-Salz 变体的封装。在Hutool中,生成一个UUID字符串方法如下:
//生成的UUID是带-的字符串,类似于:a5c8a5e8-df2b-4706-bea4-08d0939410e3
String uuid = IdUtil.randomUUID();
//生成的是不带-的字符串,类似于:b17f24ff026d40949c85a24f4f375d42
String simpleUUID = IdUtil.simpleUUID();
说明 Hutool重写java.util.UUID的逻辑,对应类为cn.hutool.core.lang.UUID,使生成不带-的UUID字符串不再需要做字符替换,性能提升一倍左右。
【2】ObjectId
ObjectId是MongoDB数据库的一种唯一ID生成策略,是 UUID version1 的变种,Hutool针对此封装了cn.hutool.core.lang.ObjectId,快捷创建方法为:
//生成类似:5b9e306a4df4f8c54a39fb0c
String id = ObjectId.next();
//方法2:从Hutool-4.1.14开始提供
String id2 = IdUtil.objectId();
【3】Snowflake
分布式系统中,有一些需要使用全局唯一ID的场景,有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。Twitter的Snowflake 算法就是这种生成器。使用方法如下:
//参数1为终端ID
//参数2为数据中心ID
Snowflake snowflake = IdUtil.getSnowflake(1, 1);
long id = snowflake.nextId();
//简单使用
long id = IdUtil.getSnowflakeNextId();
String id = snowflake.getSnowflakeNextIdStr();
⑥ 随机工具类(RandomUtil.java)
RandomUtil主要针对JDK中Random对象做封装,严格来说,Java产生的随机数都是伪随机数,因此Hutool封装后产生的随机结果也是伪随机结果。不过这种随机结果对于大多数情况已经够用。
RandomUtil.randomInt 获得指定范围内的随机数 例如我们想产生一个[10, 100)的随机数,则:
int c = RandomUtil.randomInt(10, 100);
RandomUtil.randomBytes 随机bytes,一般用于密码或者salt生成
byte[] c = RandomUtil.randomBytes(10);
RandomUtil.randomEle 随机获得列表中的元素。
RandomUtil.randomEleSet 随机获得列表中的一定量的不重复元素,返回Set
Set<Integer> set = RandomUtil.randomEleSet(CollUtil.newArrayList(1, 2, 3, 4, 5, 6), 2);
⑦ 对象JSON 工具(JSONUtil.java)
JSONUtil是针对JSONObject和JSONArray的静态快捷方法集合。
【1】JSON字符串创建
JSONUtil.toJsonStr可以将任意对象(Bean、Map、集合等)直接转换为JSON字符串。如果对象是有序的Map等对象,则转换后的JSON字符串也是有序的。
SortedMap<Object, Object> sortedMap = new TreeMap<Object, Object>() {
private static final long serialVersionUID = 1L;
{
put("attributes", "a");
put("b", "b");
put("c", "c");
}};
JSONUtil.toJsonStr(sortedMap); // 输出结果:{"attributes":"a","b":"b","c":"c"}
// 如果我们想获得格式化后的JSON,则:
JSONUtil.toJsonPrettyStr(sortedMap);
//{
// "attributes": "a",
// "b": "b",
// "c": "c"
//}
【2】JSON 字符串解析
String html = "{\"name\":\"Something must have been changed since you leave\"}";
JSONObject jsonObject = JSONUtil.parseObj(html);
jsonObject.getStr("name");
【3】 XML字符串转换为JSON
String s = "<sfzh>123</sfzh><sfz>456</sfz><name>aa</name><gender>1</gender>";
JSONObject json = JSONUtil.parseFromXml(s);
json.get("sfzh");
json.get("name");
【4】 JSON转换为XML
final JSONObject put = JSONUtil.createObj()
.set("aaa", "你好")
.set("键2", "test");
// <aaa>你好</aaa><键2>test</键2>
final String s = JSONUtil.toXmlStr(put);
【5】JSON转Bean
我们先定义两个较为复杂的Bean(包含泛型)
@Data
public class ADT {
private List<String> BookingCode;
}
@Data
public class Price {
private List<List<ADT>> ADT;
}
String json = "{\"ADT\":[[{\"BookingCode\":[\"N\",\"N\"]}]]}";
Price price = JSONUtil.toBean(json, Price.class);
price.getADT().get(0).get(0).getBookingCode().get(0);
当然,上面只是列举了Hutool的一部分功能,更多功能可以去它官网:www.hutool.cn查看。
总体来说,Hutool目前封装的这些工具类,确实非常好用,可以节省我们重复造轮子的时间,少写很多代码,帮助我们提升开发效率。
转自:https://juejin.cn/post/7363555404130811904