首页 > 应用开发 > Java > Hutool 工具不糊涂

这是我参与11月更文挑战的第3天,活动详情查看: 。还在对项目中的工具类和工具方法进行封装吗?让
Hutool帮你,它是项目中util包的友好替代,覆盖了Java开发底层的方方面面,既是大型项目中解决小问题的利器,也是小项目中的效率担当,它能让你专注业务,极大地提升开发效率,可以最大程度地避免自行封装出现的小问题、小Bug。所以,学会如何高效、准确地使用项目开发过程中所需的工具方法非常有必要,今天结合使用场景给大家分享一些实用的工具类方法,没讲清楚以及未涉及之处,望大家见谅,具体详情可参见 。
Hutool 包含对文件、流、加密解密、转码、正则、线程、XML 等 JDK 方法进行封装,放在不同的模块组件当中,当你需要对
Excel 进行操作时,你可以单独引入
hutool-poi 模块,当然分不清个模块之间功能,图省事,也可以通过引入
hutool-all 方式引入所有模块。
<dependency
>
<groupId
>cn
.hutool
<
/groupId
>
<artifactId
>hutool
-all
<
/artifactId
>
<version
>
5.7
.16
<
/version
>
<
/dependency
>
Gradle
implementation 'cn.hutool:hutool-all:5.7.16'
下面给大伙分享一些经常使用且使用的工具方法,有用到过的欢迎留言评论哦 (^▽^)
熟悉
JS 的掘友看到这两个方法一定不陌生,甚至是“旧交”了,其实
Hutool 中 的
Console 对象借鉴的就是
JS 中的语法糖。虽说是打印,和
System.out.println() / System.err.println() 还是有所不同的,最重要的是它支持
Slf4j 的字符串模版语法,会自动将对象(包括数组)转为字符串形式。
代码实例:
Console
.
log
(
"this is array: {}"
,
new
String
[
]
{
"Java"
,
"JavaScript"
,
"Python"
}
)
;
Console
.
error
(
"I'm a red error message."
)
;
这里的
{} 作为模版占位符,能够将逗号右边的变量值依次传入,从而以字符串的形式打印输出。
该类中封装了针对
Java 常见类型的转换,用于简化类型转换,同时对转换失败的异常捕获有着很好的封装,能够帮你减轻业务代码的臃肿,提升代码的优雅性,该工具类还是非常常用和实用的,必须安利一波୧(๑•̀◡•́๑)૭
代码实例:
// 转换为字符串
int number
=
10
;
Console
.
log
(
"转换成字符串后:{}"
, Convert
.
toStr
(number
)
)
;
int
[
] arr
=
{
1
,
2
,
3
,
4
,
5
}
;
Console
.
log
(Convert
.
toStr
(arr
,
"Convert to string fail! This is default value."
)
)
;
// 转换为指定类型的数组
String
[
] letters
=
{
"12"
,
"122"
,
"1223"
,
"1211"
}
;
Console
.
log
(Convert
.
toShortArray
(letters
)
)
;
Console
.
log
(Convert
.
toStrArray
(arr
)
)
;
float
[
] floatArr
=
{
1.2F
,
1.3F
,
2.0F
,
3.14f
}
;
Integer
[
] integerArr
= Convert
.
toIntArray
(floatArr
)
;
Console
.
log
(integerArr
)
;
// [1, 1, 2, 3]
// 转换为日期对象
String strDate1
=
"2021-10-11 12:03:29"
;
// toDate
Console
.
log
(
"The string of data convert to Date: {}"
, Convert
.
toDate
(strDate1
)
)
;
// 2021-10-11 12:03:29
// toLocalDateTime
Console
.
log
(
"The string of data convert to LocalDateTime: {}"
, Convert
.
toLocalDateTime
(strDate1
)
)
;
// 2021-10-11T12:03:29
// 转换成集合
String
[
] langs
=
{
"Java"
,
"JavaScript"
,
"Python"
,
"C++"
,
"GoLang"
,
"TypeScript"
,
"Kotlin"
}
;
// 通过 Convert.convert(Class<T>, Object) 方法可以将任意类型转换为指定类型
ArrayList arrayList
= Convert
.
convert
(ArrayList
.class
, langs
)
;
// 也可以这样转集合
List
<String
> langList
= Convert
.
toList
(String
.class
, langs
)
;
Console
.
log
(
"String array is converted to ArrayList: {}"
, arrayList
)
;
Console
.
log
(
"String array is converted to List: {}"
, langList
)
;
// 转成指定类型的集合
Object
[
] objArr
=
{
"a"
,
"你"
,
"好"
,
""
,
1
}
;
// TypeReference 对象可以对嵌套泛型进行类型转换
List
<String
> strList
= Convert
.
convert
(
new
TypeReference
<List
<String
>>
(
)
{
}
, objArr
)
;
Console
.
log
(
"使用 TypeReference 对象可以对嵌套泛型进行类型转换:{}"
, strList
)
;
字符串转为
16 进制(
Hex)和
Unicode 串
// 字符串转为 16 进制(Hex)
String desc
=
"大家好,我的名字叫 HUALEI !"
;
// 因为字符串牵涉到编码问题,因此必须传入编码对象
String hexStr
= Convert
.
toHex
(desc
, CharsetUtil
.
CHARSET_UTF_8
)
;
Console
.
log
(
"将字符串转为 Hex 字符串:{}"
, hexStr
)
;
// e5a4a7e5aeb6e5a5bdefbc8ce68891e79a84e5908de5ad97e58fab204855414c454920efbc81
// Hex 字符串转换回去
String originStr
= Convert
.
hexToStr
(hexStr
, CharsetUtil
.
CHARSET_UTF_8
)
;
Console
.
log
(
"将 Hex 字符串转换回原先字符串:{}"
, originStr
)
;
/*
如果把各种文字编码形容为各地的方言,那么 Unicode 就是世界各国合作开发的一种语言。
字符串转为 Unicode(统一码 / 万国码 / 单一码),它是为了解决传统字符编码方案弊端(繁杂不统一,导致编码格式不一致引发的乱码问题)
Unicode 为每种语言中的每个字符设定了 统一 并且 唯一 的 二进制编码
以满足 跨语言、跨平台 进行 文本转换、处理 的需求
*/
// 将字符串转换成 Unicode
String unicodeStr
= Convert
.
strToUnicode
(desc
)
;
Console
.
log
(
"字符串转换成 Unicode 串:{}"
, unicodeStr
)
;
// \u5927\u5bb6\u597d\uff0c\u6211\u7684\u540d\u5b57\u53eb HUALEI \uff01
字符编码方式转换(编码与解码)
String a
=
"我不是乱码"
;
// 使用 UTF8 字符编码解码为 ISO_8859_1 编码方式的字符串
String mess
= Convert
.
convertCharset
(a
, CharsetUtil
.
UTF_8
, CharsetUtil
.
ISO_8859_1
)
;
Console
.
log
(
"ISO_8859_1 编码方式的中文乱码:{}"
, mess
)
;
// 转换后 mess 为乱码 => æä¸æ¯ä¹±ç
// 使用 ISO_8859_1 字符编码解码为原先的 UTF8 编码方式的字符串,将乱码转为正确的编码方式:
String raw
= Convert
.
convertCharset
(mess
, CharsetUtil
.
ISO_8859_1
,
"UTF-8"
)
;
Console
.
log
(
"将乱码转为正确的编码后:{}"
, raw
)
;
// 我不是乱码
中文大/小写数字、金额相关转换
// 金额转中文表达(最多保留到小数点后两位)
double money
=
18.88D
;
String chineseWord
= Convert
.
digitToChinese
(money
)
;
Console
.
log
(
"金额转中文表达:{}"
, chineseWord
)
;
// 壹拾捌元捌角捌分
// 金额转英文表达(最多保留到小数点后两位)
String englishWord
= Convert
.
numberToWord
(money
)
;
Console
.
log
(
"金额转英文表达:{}"
, englishWord
)
;
// EIGHTEEN AND CENTS EIGHTY EIGHT ONLY
double amount
=
102389942.32D
;
// 数字转中文大写(例:壹仟,最多保留到小数点后两位) isUseTraditional => true
String traditionalChinese
= Convert
.
numberToChinese
(amount
,
true
)
;
// 数字转中文小写(例:一千) isUseTraditional => false
String nonTraditionalChinese
= Convert
.
numberToChinese
(amount
,
false
)
;
Console
.
log
(
"数字转中文大写,传统:{};非传统:{}"
, traditionalChinese
, nonTraditionalChinese
)
;
// 传统:壹亿零贰佰叁拾捌万玖仟玖佰肆拾贰点叁贰;非传统:一亿零二百三十八万九千九百四十二点三二
// 中文大写壹仟叁佰转成纯数字
Console
.
log
(
"中文大写壹仟叁佰转成数字:{}"
, Convert
.
chineseToNumber
(
"壹仟叁佰"
)
)
;
// 1300
// 数字简化 1000 => 1k; 10000 => 1w(最多保留到小数点后两位)
String simple
= Convert
.
numberToSimple
(amount
)
;
Console
.
log
(
"{} 简化为:{}"
, amount
, simple
)
;
// 10238.99w
convertTime(目标值,目标值时间单位,转换后的时间单位) 方法主要用于转换时长单位,比如一个很大的毫秒,我想获得这个毫秒数换算成多少天:
// 毫秒数
long ms
=
100000000L
;
long msToDays
= Convert
.
convertTime
(ms
, TimeUnit
.
MILLISECONDS
, TimeUnit
.
DAYS
)
;
Console
.
log
(
"{} 毫秒约等于 {} 天"
, ms
, msToDays
)
;
// 100000000 毫秒约等于 1 天
原始类型和包装类型之间的转换
// Integer 包装类
Class
<Integer
> wrapClass
= Integer
.class
;
// Integer 去除包装类 => int
Class
<
?
> unWraped
= Convert
.
unWrap
(wrapClass
)
;
// int
Console
.
log
(
"Integer 包装类去包装化:{}"
, unWraped
)
;
// 原始类
Class
<
?
> primitiveClass
= long
.class
;
// 将原始类型转换成包装类
Class
<
?
> wraped
= Convert
.
wrap
(primitiveClass
)
;
// class java.lang.Long
Console
.
log
(
"long 原始类包装化:{}"
, wraped
)
;
DateUtil
DateTime 日期时间工具类
对于
java.util.Date 对象是不是还停留在被
Thu Nov dd HH:mm:ss CST yyyy 支配的恐惧中?数字英文单词缩写的混杂让人看起来非常不舒服,如果你想将其转换成
yyyy-MM-dd / yyyy-MM-dd HH:mm:ss 时间格式字符串,你是不是得先
new 一个
SimpleDateFormat,通过
pattern 参数进行初始化格式化器,时间格式不熟练的可能还要百度一下,甚是麻烦。
为了便捷,
Hutool 工具使用了一个
DateTime 类来替代之,继承自
Date ,重写了
toString() 方法,直接放回
yyyy-MM-dd HH:mm:ss 形式的字符串,方便在输出时的调用(例如日志记录等),提供了众多便捷的方法对日期对象操作。
代码实例:
// 计时器,计算被其包裹的代码片段执行时间
final TimeInterval timeInterval
= DateUtil
.
timer
(
)
;
// 根据 birthday 计算现在的年龄
String dateStr
=
"2000年05月26日"
;
Date birthday
= Convert
.
toDate
(dateStr
)
;
// 可以通过 DatePattern 指定 dateStr 日期时间格式进行解析,如果没有第二个参数,则会自动寻找合适的格式(支持多种格式)进行解析
// DateTime dateTime = new DateTime(dateStr, DatePattern.CHINESE_DATE_PATTERN);
int age
= DateUtil
.
ageOfNow
(birthday
)
;
// 或 DateUtil.ageOfNow(dateTime);
Console
.
log
(
"{} 出生的小伙子,如今已经 {} 岁了!"
, dateStr
, age
)
;
// 获取当前时间,格式:yyyy-MM-dd HH:mm:ss => DateTime 类型
Date currentDate
= DateUtil
.
date
(
)
;
// 2021-11-02 08:57:54
// 等价于 DateTime currentDateTime = new DateTime();
// 不同于 new Date() => Tue Nov 02 08:57:54 CST 2021
Console
.
log
(
"DateUtil.date() 得到当前时间(yyyy-MM-dd HH:mm:ss):"
, currentDate
)
;
// 将特殊的日期字符串转换为 DateTime 对象
String strDate2
=
"2021年11月02日 12时03分29秒"
;
// 根据格式化模版将字符串日期转换为 Date 对象
Console
.
log
(
"Use DateUtil.parse() method convert to Date: {}"
, DateUtil
.
parse
(strDate2
,
"yyyy年MM月dd日 HH时mm分ss秒"
)
)
;
// 2021-11-02 12:03:29
// 等价于 new DateTime(strDate2);
// 方式一:当前毫秒数转换为 DateTime 时间,格式:yyyy-MM-dd HH:mm:ss
Date msToDateTime1
= DateUtil
.
date
(Calendar
.
getInstance
(
)
)
;
// 2021-11-02 08:57:54
Console
.
log
(
"当前毫秒数转换为 DateTime 时间,方式一:"
, msToDateTime1
)
;
// 方式二:当前毫秒数转换成 DateTime 时间,格式:yyyy-MM-dd HH:mm:ss
Date msToDateTime2
= DateUtil
.
date
(System
.
currentTimeMillis
(
)
)
;
// 2021-11-02 08:57:54
Console
.
log
(
"当前毫秒数转换为 DateTime 时间,方式二:"
, msToDateTime2
)
;
// 当前日期字符串,格式:yyyy-MM-dd
String today
= DateUtil
.
today
(
)
;
// 2021-11-02
Console
.
log
(
"当前日期字符串,格式:yyyy-MM-dd:{}"
, today
)
;
// 将 Date 对象格式化为日期字符串,格式:yyyy-MM-dd
String formatDateStr
= DateUtil
.
format
(
new
Date
(
)
,
"yyyy-MM-dd"
)
;
Console
.
log
(
"Use DateUtil.format() method convert to Date: {}"
, formatDateStr
)
;
// 获取日期时间(DateTime)的 Time 字符串,格式:HH:mm:ss
String formatTimeStr
= DateUtil
.
formatTime
(
new
DateTime
(
)
)
;
Console
.
log
(
"Use DateUtil.formatTime() method only covert Date to HH:mm:ss:{}"
, formatTimeStr
)
;
// 星座(zodiac sign)
String zodiac
= DateUtil
.
getZodiac
(DateUtil
.
month
(birthday
)
,
(
(int
) DateUtil
.
betweenDay
(DateUtil
.
beginOfMonth
(birthday
)
, birthday
,
false
)
)
)
;
// 属相(chinese zodiac)
String chineseZodiac
= DateUtil
.
getChineseZodiac
(DateUtil
.
year
(birthday
)
)
;
Console
.
log
(
"{} 生日的人,星座是:{},属 {} 的。"
, birthday
, zodiac
, chineseZodiac
)
;
// 判断今年是不是平闰年
boolean isLeapYear
= DateUtil
.
isLeapYear
(DateUtil
.
year
(
new
Date
(
)
)
)
;
Console
.
log
(
"{}年是闰年吗?{}"
, DateUtil
.
year
(
new
Date
(
)
)
, isLeapYear
)
;
// 得到一个美化过后的花费时间,即加上中文单位
String spendTimePretty
= timeInterval
.
intervalPretty
(
)
;
// 运行时间转换为秒为单位
long sec
= timeInterval
.
intervalSecond
(
)
;
// 返回花费时间,并重置开始时间
long spendTimeAndRestart
= timeInterval
.
intervalRestart
(
)
;
Console
.
log
(
"测试运行时间(无单位不美化):"
, spendTimeAndRestart
)
;
Console
.
log
(
"测试运行时间(有单位带美化):"
, spendTimePretty
)
;
Console
.
log
(
"测试运行时间,转换为秒:{}"
, sec
)
;
获取指定天/周/月/季度/年的开始/结束时间,返回
DateTime,格式为:
yyyy-MM-dd HH:mm:ss
DateTime beginOfDayTime
= DateUtil
.
beginOfDay
(
new
Date
(
)
)
;
Console
.
log
(
"今天开始时间:{}"
, beginOfDayTime
)
;
// 2021-11-03 00:00:00
DateTime beginOfYearTime
= DateUtil
.
beginOfYear
(
new
Date
(
)
)
;
Console
.
log
(
"今年开始时间:{}"
, beginOfYearTime
)
;
// 2021-01-01 00:00:00
DateTime endOfYearTime
= DateUtil
.
endOfYear
(
new
Date
(
)
)
;
Console
.
log
(
"今年结束时间:{}"
, endOfYearTime
)
;
// 2021-12-31 23:59:59
日期时间偏移:即对某个日期增减分、小时、天等等
// 将当前时间增加半个小时
DateTime halfHourLater
= DateUtil
.
offset
(currentDate
, DateField
.
MINUTE
,
30
)
;
// 等同于:DateUtil.offsetHour(currentDate, 30);
Console
.
log
(
"当前时间是 {},半个小时后是:{}"
, currentDate
, halfHourLater
)
;
// 五天后的现在时间
DateTime fiveDaysFromNow
= DateUtil
.
offsetDay
(currentDate
,
5
)
;
Console
.
log
(
"当前时间是 {},五天后是:{}"
, currentDate
, fiveDaysFromNow
)
;
// 针对当前时间,提供了更为简化的偏移方法
Console
.
log
(
"昨天的现在是:{}"
, DateUtil
.
yesterday
(
)
)
;
Console
.
log
(
"明天的现在是:{}"
, DateUtil
.
tomorrow
(
)
)
;
Console
.
log
(
"上周天的现在是:{}"
, DateUtil
.
lastWeek
(
)
)
;
Console
.
log
(
"下周的现在是:{}"
, DateUtil
.
nextWeek
(
)
)
;
Console
.
log
(
"上个月的现在是:{}"
, DateUtil
.
lastMonth
(
)
)
;
Console
.
log
(
"下个月的现在是:{}"
, DateUtil
.
nextMonth
(
)
)
;
计算两个时间的间隔
// 当前时间
DateTime currentDateTime
=
new
DateTime
(
)
;
String dateTimeStrStart
=
"1949/10/01"
;
Date startTime
= Convert
.
toDate
(dateTimeStrStart
)
;
long betweenDays
= DateUtil
.
between
(startTime
,
new
DateTime
(
)
, DateUnit
.
DAY
)
;
Console
.
log
(
"距离新中国成立,已经过了 {} 天"
, betweenDays
)
;
// 下班时间(当天 17:00:00 )
Date getOffTime
= DateUtil
.
offsetHour
(DateUtil
.
beginOfDay
(currentDateTime
)
,
17
)
;
Console
.
log
(
"下班时间是:{}"
, getOffTime
)
;
long distance
= DateUtil
.
between
(getOffTime
, currentDateTime
, DateUnit
.
SECOND
,
true
)
;
// 间隔时间设置为秒
Console
.
log
(
"距离下班还剩 {} 秒"
, distance
)
;
// 格式化间隔时间
Console
.
log
(
"距离下班还剩 {} 精确到秒"
, DateUtil
.
formatBetween
(getOffTime
, currentDateTime
, BetweenFormatter
.Level
.
SECOND
)
)
;
针对
Object 通用的工具类方法,不区分是
String 还是
Object 、
Array 还是
Collection。
代码实例:
判断
null /
blank string
final String blankStr
=
" "
;
final String nullStr
=
null
;
final String dateStr
=
null
;
// isEmpty/isNull 只有为 null 才返回 true
System
.out
.
println
(ObjectUtil
.
isEmpty
(blankStr
)
)
;
// false
System
.out
.
println
(ObjectUtil
.
isEmpty
(nullStr
)
)
;
// true
System
.out
.
println
(ObjectUtil
.
isNull
(nullStr
)
)
;
// true
System
.out
.
println
(ObjectUtil
.
isNull
(blankStr
)
)
;
// false
//java学习交流:737251827 进入可领取学习资源及对十年开发经验大佬提问,免费解答!
// null/空格字符串都是 blank
System
.out
.
println
(ObjectUtil
.
defaultIfBlank
(blankStr
,
"目标字符串为空,我是默认"
)
)
;
// 走 defaultValue
System
.out
.
println
(ObjectUtil
.
defaultIfBlank
(nullStr
,
"目标字符串为空,我是默认"
)
)
;
// 走 defaultValue
// 此处判断如果dateStr为null,则调用`Instant.now()`,不为null则执行`DateUtil.parse`
System
.out
.
println
(ObjectUtil
.
defaultIfNull
(dateStr
,
(
)
-
> DateUtil
.
parse
(dateStr
, DatePattern
.
NORM_DATETIME_PATTERN
)
.
toInstant
(
)
, Instant
.
now
(
)
)
)
;
System
.out
.
println
(ObjectUtil
.
defaultIfNull
(nullStr
,
"目标字符串为 null ,我是默认"
)
)
;
// 走 defaultValue
System
.out
.
println
(ObjectUtil
.
defaultIfNull
(blankStr
,
"目标字符串为 null ,我是默认"
)
)
;
// blankStr
注意: ObjectUtil.isNull() 方法不能判断对象中字段为空的情况,如果需要检查Bean对象中字段是否全空,需使用
BeanUtil.isEmpty() 方法进行判定。
判断两个对象是否相等,等价于
Objects.equals() 方法
ObjectUtil
.
equals
(nullStr
, dateStr
)
;
// true
ObjectUtil
.
equals
(
"HUALIE"
,
"HUALEI"
)
;
// true
// 等价于
Objects
.
equals
(nullStr
, dateStr
)
;
// true
计算对象长度
int
[
] array
=
new
int
[
]
{
1
,
2
,
3
,
4
,
5
}
;
// 计算数组长度
int length
= ObjectUtil
.
length
(array
)
;
// 5
Map
<String
, String
> map
=
new
HashMap
<
>
(
)
;
map
.
put
(
"a"
,
"a1"
)
;
map
.
put
(
"b"
,
"b1"
)
;
map
.
put
(
"c"
,
"c1"
)
;
// 计算 Map 大小
length
= ObjectUtil
.
length
(map
)
;
// 3
如果是字符串调用其
length() 方法,集合类调用其
size() 方法,数组调用其
length 属性,其他可遍历对象遍历计算长度。
![]()
↑ 和这个类类似,但是相较于
StringUtils 这个类写起来更短,更能偷懒 [狗头],类中常用的方法有
isBlank()、
isNotBlank()、
isEmpty()、
isNotEmpty() 主要用于对字符串的判空,这里就不赘述了。
代码实例:
// 去除前缀
String
[
] tableNames
=
{
"tb_user"
,
"t_mall"
,
"province"
,
"t_capital"
,
"tb_task"
}
;
for
(int i
=
0
; i
< tableNames
.length
; i
++
)
{
if
(StrUtil
.
containsAnyIgnoreCase
(tableNames
[i
]
,
"tb_"
,
"t_"
)
)
{
// 去除前缀忽略大小写
tableNames
[i
]
= StrUtil
.
removePrefixIgnoreCase
(tableNames
[i
]
,
"tb_"
)
;
// 去除前缀忽略大小写
tableNames
[i
]
= StrUtil
.
removePrefixIgnoreCase
(tableNames
[i
]
,
"t_"
)
;
}
}
Console
.
log
(
"移除表名前缀后:{}"
,
(Object
) tableNames
)
;
// [user, mall, province, capital, task]
// 去除后缀
String fileName
= StrUtil
.
removeSuffix
(
"HUALEI.png"
,
".png"
)
;
Console
.
log
(
"去除文件.扩展名后:{}"
, fileName
)
;
// HUALEI
// 字符创常量,包括点、空字符串、换行符,还有一些 HTML 中的转义字符
System
.out
.
println
(StrUtil
.
AT
.
concat
(
"HUALEI"
)
.
concat
(StrUtil
.
DOT
)
.
concat
(StrUtil
.
LF
)
)
;
// @HUALEI.
// 使用字符串模板代替字符串拼接
String template
=
"{}爱{},我爱你,蜜雪冰城{}"
;
String str
= StrUtil
.
format
(template
,
"你"
,
"我"
,
"甜蜜蜜"
)
;
// 你爱我,我爱你,蜜雪冰城甜蜜蜜
CollUtil | CollStreamUtil 集合处理工具类
这两个类主要封装的是对数组、列表等集合类的操作方法,集合在开发中占很大一部分,必须重点掌握,以提高我们的开发效率。
代码实例:
模拟数据库排序分页,返回一个
PageResult
List
<Fruit
> fruits
= fruitMapper
.
selectList
(Wrappers
.
emptyWrapper
(
)
)
;
// 总记录数
long totalCount
= fruits
.
size
(
)
;
// 当前页
int currentPage
=
1
;
// 每页记录数
int pageSize
=
10
;
// 当前页索引,从 0 开始,表示第一页
int pageNo
= currentPage
-
1
;
// 默认分页列表
List
<Fruit
> defaultPageList
= CollUtil
.
page
(pageNo
, pageSize
, fruits
)
;
// 按照记录更新时间进行排序分页列表
List
<Fruit
> orderPageList
= CollUtil
.
sortPageAll
(pageNo
, pageSize
, Comparator
.
comparing
(Fruit
:
:getUpdateTime
)
, fruits
)
;
// 重新用分页参数及记录列表组装 PageResult 分页结果对象
PageResult pageResult
=
new
PageResult
(orderPageList
, totalCount
, pageSize
, currentPage
)
)
;
System
.out
.
println
(
"当前页数:"
+ pageResult
.
getCurrPage
(
)
)
;
System
.out
.
println
(
"每页记录数:"
+ pageResult
.
getPageSize
(
)
)
;
System
.out
.
println
(
"总记录数:"
+ pageResult
.
getTotalCount
(
)
)
;
System
.out
.
println
(
"总页数:"
+ pageResult
.
getTotalPage
(
)
)
;
// 当前页记录列表
pageResult
.
getList
(
)
.
forEach
(System
.out
:
:println
)
;
获取表头别名映射
// 字段名列表
List
<String
> headerNameList
=
new
ArrayList
<
>
(
)
;
// 使用反射工具获取全部表头名
for
(Field field
: ReflectUtil
.
getFields
(ProvinceExcelVO
.class
)
)
{
if
(
!StrUtil
.
equals
(field
.
getName
(
)
,
"serialVersionUID"
)
)
{
headerNameList
.
add
(field
.
getName
(
)
)
;
}
}
// 表头别名列表
List
<String
> aliasList
= CollUtil
.
newArrayList
(
"省份名称"
,
"简称"
,
"面积(km²)"
,
"人口数量(万)"
,
"著名景点"
,
"邮政编码"
,
"省会城市"
,
"别称"
,
"气候类型"
,
"车牌号"
)
;
// 一一对应,形成表头别名映射
Map
<String
, String
> headerAliasMap
= CollUtil
.
zip
(fieldNameList
, aliasList
)
;
建立省名和省份对象之间的
Map
// 省份表中所有省份信息
List
<Province
> provinces
= provinceMapper
.
selectList
(Wrappers
.
emptyWrapper
(
)
)
;
// 使用 CollStreamUtil 集合流工具,一行代码解决
Map
<String
, Province
> provinceMap
= CollStreamUtil
.
toIdentityMap
(provinces
, Province
:
:getProvince
)
;
// 等价于
Map
<String
, List
<Province
>> provinceMap
=
provinces
.
stream
(
)
.
collect
(Collectors
.
toMap
(Province
:
:getProvince
, Arrays
:
:asList
)
)
;
// 又等价于,结合 Convert 方法二:
Map
<String
, List
<Province
>> provinceMap
=
provinces
.
stream
(
)
.
collect
(Collectors
.
toMap
(Province
:
:getProvince
, p
-
> Convert
.
toList
(Province
.class
, p
)
)
)
;
// 获取江西省省份信息
Console
.
log
(
"江西省省份信息为:{}"
, provinceMap
.
get
(
"江西省"
)
)
;
将所有省份按照主键
pid 进行分组
Map
<Integer
, List
<Province
>> groupByKey
= CollStreamUtil
.
groupByKey
(CollUtil
.
unionAll
(provinces
, provinces
)
, Province
:
:getPid
)
;
// 等价于
Map
<Integer
, List
<Province
>> groupByKey
= CollUtil
.
unionAll
(provinces
, provinces
)
.
stream
(
)
.
collect
(Collectors
.
groupingBy
(Province
:
:getPid
, Collectors
.
toList
(
)
)
)
;
提取省份信息列表中省份名
List
<String
> provinceNameList
= CollStreamUtil
.
toList
(provinces
, Province
:
:getProvince
)
;
// 等价于
List
<String
> provinceNameList
= provinces
.
stream
(
)
.
map
(Province
:
:getProvince
)
.
collect
(Collectors
.
toList
(
)
)
;
两个
map 根据
key 进行合并(
merge)操作,最终结果期望为:(
key:
pid,
value:
province(省份名) + "-" + abbr(省份简称))
// (key: pid, value: province)
Map
<Integer
, String
> pidToProvince
= CollStreamUtil
.
toMap
(provinces
, Province
:
:getPid
, Province
:
:getProvince
)
;
// 等价于
Map
<Integer
, String
> pidToProvince
=
provinces
.
stream
(
)
.
collect
(Collectors
.
toMap
(Province
:
:getPid
, Province
:
:getProvince
)
)
;
// (key: pid, value: abbr)
Map
<Integer
, String
> pidToAbbr
= CollStreamUtil
.
toMap
(provinces
, Province
:
:getPid
, Province
:
:getAbbr
)
;
// 等价于
Map
<Integer
, String
> pidToProvince
=
provinces
.
stream
(
)
.
collect
(Collectors
.
toMap
(Province
:
:getPid
, Province
:
:getAbbr
)
)
;
// 根据 key 合并 Map,key 相同则走 merge 规则
Map
<Integer
, String
> mergeResult
= CollStreamUtil
.
merge
(pidToProvince
, pidToAbbr
,
(province
, abbr
)
-
> province
+
"-"
+ abbr
)
;
RandomUtil 随机工具
RandomUtil 工具类主要是对
Random 对象的封装,用于产生随机数/列表,虽然是伪随机数,但是对于大多数使用场景还是够用的。
代码实例:
// 生成指定范围内的随机整数
for
(int i
=
0
; i
<
10
; i
++
)
{
System
.out
.
println
(RandomUtil
.
randomInt
(
0
,
100
)
)
;
}
List
<String
> randomList
=
new
ArrayList
<
>
(
)
;
// 生成随机字符串(只包含数字和字符)
for
(int i
=
0
; i
<
10
; i
++
)
{
randomList
.
add
(RandomUtil
.
randomString
(
5
)
)
;
}
// 从指定列表中随机取 5 个数
List
<Integer
> eleList
= RandomUtil
.
randomEleList
(Arrays
.
asList
(
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
)
,
5
)
;
// 随机从字符串列表中取出 5 个,不重复(取出的个数不能超过列表的大小)
Set
<String
> eleSet
= RandomUtil
.
randomEleSet
(randomList
,
5
)
;
// 权重随机生成器,传入带权重的对象,然后根据权重随机获取对象
WeightRandom weightRandom
= RandomUtil
.
weightRandom
(
new
WeightRandom
.WeightObj
[
]
{
new
WeightRandom
.WeightObj
(
"HUA"
,
60
)
,
new
WeightRandom
.WeightObj
(
"L"
,
10
)
,
new
WeightRandom
.WeightObj
(
"EI"
,
30
)
}
)
;
// 随机取 10 次,"HUA" 字符串出现的次数是最多的
for
(int i
=
0
; i
<
10
; i
++
)
{
System
.out
.
println
(weightRandom
.
next
(
)
)
;
}
ExcelUtil Excel 操作工具类
该类是对
Apache 的
POI 库的二次封装,便捷了对
MS Office 文档操作,使用该类时,需要用户执行导入
poi-ooxml 依赖,这个包会自动关联引入
poi 包,可以很好的支持
Office2007+ 的文档格式。
注意
开始使用前,需导入依赖:
<dependency
>
<groupId
>org
.apache
.poi
<
/groupId
>
<artifactId
>poi
-ooxml
<
/artifactId
>
<version
>$
{poi
.version
}
<
/version
>
<
/dependency
>
未引入使用其中的工具方法,会报错:
You need to add dependency of 'poi-ooxml' to your project, and version >= 4.1.2
代码实例:
// 写入 Excel 中的数据源
List
<Province
> provinces
= provinceMapper
.
selectList
(Wrappers
.
emptyWrapper
(
)
)
;
// 写出文件路径
String inputPath
=
"D:/桌面/导出省份信息.xlsx"
;
// 通过工具类创建一个 Writer 写入对象
ExcelWriter excelWriter
= ExcelUtil
.
getWriter
(inputPath
,
"省份信息表"
)
;
// 自定义表头名(方法一)
excelWriter
.
addHeaderAlias
(
"pid"
,
"省份ID"
)
;
excelWriter
.
addHeaderAlias
(
"province"
,
"省份"
)
;
excelWriter
.
addHeaderAlias
(
"abbr"
,
"简称"
)
;
excelWriter
.
addHeaderAlias
(
"area"
,
"面积(km²)"
)
;
excelWriter
.
addHeaderAlias
(
"population"
,
"人口数量(万)"
)
;
excelWriter
.
addHeaderAlias
(
"attraction"
,
"著名景点"
)
;
excelWriter
.
addHeaderAlias
(
"capital"
,
"省会"
)
;
// 自定义表头名(方法二)
Map
<String
, String
> headerAlias
=
new
LinkedHashMap
<
>
(
7
)
;
//java学习交流:737251827 进入可领取学习资源及对十年开发经验大佬提问,免费解答!
for
(Field field
: ReflectUtil
.
getFields
(Province
.class
)
)
{
String name
= field
.
getName
(
)
;
String alias
;
switch
(name
)
{
case
"pid"
:
alias
=
"省份ID"
;
break
;
case
"province"
:
alias
=
"省份"
;
break
;
case
"abbr"
:
alias
=
"简称"
;
break
;
case
"area"
:
alias
=
"面积(km²)"
;
break
;
case
"population"
:
alias
=
"人口数量(万)"
;
break
;
case
"attraction"
:
alias
=
"著名景点"
;
break
;
case
"capital"
:
alias
=
"省会"
;
break
;
default
:
alias
=
null
;
}
if
(ObjectUtil
.
isNotEmpty
(alias
)
)
{
headerAlias
.
put
(field
.
getName
(
)
, alias
)
;
}
}
// 使用无序的 HashMap 入参表头也跟着无序,需使用 LinkedHashMap ,保证有序
excelWriter
.
setHeaderAlias
(headerAlias
)
;
// 写出数据源到 Excel 当中,使用默认样式,强制输出标题
excelWriter
.
write
(provinces
,
true
)
;
// 关闭 writer ,释放内存
excelWriter
.
close
(
)
;
撰文不易,欢迎大家点赞、评论,你的关注、点赞是我坚持的不懈动力,感谢大家能够看到这里!Peace & Love。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70010294/viewspace-2848468/ ,如需转载,请注明出处,否则将追究法律责任。