0.前言
Hutool是一个Java工具包,也只是一个工具包,它帮助我们简化每一行代码,减少每一个方法。Hutool基本上覆盖了日常开发中涉及的所有工具方法。包括字符串操作、日期操作、Excel、HTTP客户端、JSON解析等等。强烈推荐大家使用。官方文档。接下来通过项目源码中的测试用例来学习和入门Hutool,看完测试用例你就会惊叹:牛掰!Gitee和GitHub上都有这个项目,这里使用Gitee,clone会快一点。GitHub clone慢的问题也可以通过Gitee导入GitHub项目的方式解决
1. 项目结构
模块 | 介绍 |
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中有完备的注释,在实际使用中我们只需要大概知道你需要使用的工具类的名字,然后通过看源码的注释就可以直接使用了,例如:
当然也可以直接看API文档:https://apidoc.gitee.com/loolly/hutool/
2.常用工具类介绍
Console.log();方法是Hutool提供在控制台打印的方法,类似System.out.printf。以下实例中将使用这个方法。
2.1 字符串工具类:StrUtil
API文档 此工具类包含有28个工具方法,在实际开发中使用的频率很大。同时还继承CharSequenceUtil
字符分割可忽略空格:
@Test
public void splitTest() {
String str = "a,b ,c,d,,e";
List<String> split = StrUtil.split(str, ',', -1, true, true);
Console.log(split);
}
Console:
[a, b, c, d, e]
字符串处理不可见字符:
@Test
public void trimTest() {
String blank = " 哈哈 ";
String trim = StrUtil.trim(blank);
Console.log(trim);
}
Console:
哈哈
按指定长度分割字符串
@Test
public void cutTest() {
String str = "aaabbbcccdddaadfdfsdfsdf0";
String[] cut = StrUtil.cut(str, 4);
Console.log(cut);
}
Console:
[aaab, bbcc, cddd, aadf, dfsd, fsdf, 0]
返回类型 | 方法名 |
static StringBuilder | builder() 创建StringBuilder对象 |
static StringBuilder | builder() 创建StringBuilder对象 |
static StringBuilder | builder(int capacity) 创建StringBuilder对象 |
static String | fill(String str, char filledChar, int len, boolean isPre) 将已有字符串填充为规定长度,如果已有字符串超过这个长度则返回这个字符串 |
static String | fillBefore(String str, char filledChar, int len) 将已有字符串填充为规定长度,如果已有字符串超过这个长度则返回这个字符串 字符填充于字符串前 |
static String | format(CharSequence template, Map<?,?> map) 格式化文本,使用 {varName} 占位 map = {a: “aValue”, b: “bValue”} format("{a} and {b}", map) —=》 aValue and bValue |
static String | format(CharSequence template, Map<?,?> map, boolean ignoreNull) 格式化文本,使用 {varName} 占位 map = {a: “aValue”, b: “bValue”} format("{a} and {b}", map) —=》 aValue and bValue |
static StringReader | getReader(CharSequence str) 获得StringReader |
static StringWriter | getWriter() 获得StringWriter |
static boolean | isBlankIfStr(Object obj) 对象是字符串是否为空白 |
static boolean | isEmptyIfStr(Object obj) 如果对象是字符串是否为空串. |
static String | reverse(String str) 反转字符串 例如:abcd =》dcba |
static double | similar(String str1, String str2) 计算两个字符串的相似度 |
static String | similar(String str1, String str2, int scale) 计算两个字符串的相似度百分比 |
static String | str(byte[] data, Charset charset) 解码字节码 |
static String | str(Byte[] data, Charset charset) 解码字节码 |
static String | str(byte[] bytes, String charset) 将byte数组转为字符串 |
static String | str(Byte[] bytes, String charset) 将Byte数组转为字符串 |
static String | str(ByteBuffer data, Charset charset) 将编码的byteBuffer数据转换为字符串 |
static String | str(ByteBuffer data, String charset) 将编码的byteBuffer数据转换为字符串 |
static String | str(Object obj, Charset charset) 将对象转为字符串 |
static String | uuid() 生成随机UUID |
2.2 数字工具类NumberUtil
API文档 以下选取常用的方法列出,详尽的API可查看文档或源码
返回类型 | 方法名 |
static double | add(double v1, double v2) 提供精确的加法运算 |
static int | compare(byte x, byte y) 比较两个值的大小 |
static int | divisor(int m, int n) 最大公约数 |
static boolean | equals(BigDecimal bigNum1, BigDecimal bigNum2) 比较大小,值相等 返回true 此方法通过调用BigDecimal.compareTo(BigDecimal)方法来判断是否相等 此方法判断值相等时忽略精度的,即0.00 == 0 |
static boolean | equals(double num1, double num2) 比较大小,值相等 返回true 此方法通过调用Double.doubleToLongBits(double)方法来判断是否相等 此方法判断值相等时忽略精度的,即0.00 == 0 |
static boolean | equals(float num1, float num2) 比较大小,值相等 返回true 此方法通过调用Float.floatToIntBits(float)方法来判断是否相等 此方法判断值相等时忽略精度的,即0.00 == 0 |
static boolean | isInteger(String s) 判断String是否是整数 支持10进制 |
static boolean | isNumber(CharSequence str) 是否为数字,支持包括: |
static BigDecimal | max(BigDecimal… numberArray) 取最大值 |
static double | max(double… numberArray) 取最大值 |
static int | parseInt(String number) 解析转换数字字符串为int型数字,规则如下: |
static long | parseLong(String number) 解析转换数字字符串为long型数字,规则如下: |
static Number | parseNumber(String numberStr) 将指定字符串转换为Number 对象 |
static int | partValue(int total, int partCount) 把给定的总数平均分成N份,返回每份的个数 当除以分数有余数时每份+1 |
static int[] | range(int stop) 从0开始给定范围内的整数列表,步进为1 |
static BigDecimal | round(BigDecimal number, int scale) 保留固定位数小数 采用四舍五入策略 RoundingMode.HALF_UP例如保留2位小数:123.456789 =》 123.46 |
2.3 BeanUtil
API文档 把一个拥有对属性进行set和get方法的类,我们就可以称之为JavaBean。日常开发中我们也时常遇到Bean之间转换的需求,map,list之间的转换。使用此工具类也会特别方便。
返回类型 | 方法名 |
static Map<String,Object> | beanToMap(Object bean) 对象转Map,不进行驼峰转下划线,不忽略值为空的字段 |
static Map<String,Object]]> | beanToMap(Object bean, boolean isToUnderlineCase, boolean ignoreNullValue) 对象转Map |
static void | copyProperties(Object source, Object target, boolean ignoreCase) 复制Bean对象属性 |
static void | descForEach(Class<?> clazz, Consumer<? super PropDesc> action) 遍历Bean的属性 |
static T | fillBeanWithMap(Map<?,?> map, T bean, boolean isIgnoreError) 使用Map填充Bean对象 |
static T | toBean(Class beanClass, ValueProvider valueProvider, CopyOptions copyOptions) ServletRequest 参数转Bean |
static T | toBean(Object source, Class clazz) 对象或Map转Bean |
static T | toBean(Object source, Class clazz, CopyOptions options) 对象或Map转Bean |
static T | toBeanIgnoreCase(Object source, Class clazz, boolean ignoreError) 对象或Map转Bean,忽略字段转换时发生的异常 |
static T | toBeanIgnoreError(Object source, Class clazz) 对象或Map转Bean,忽略字段转换时发生的异常 |
static T | trimStrFields(T bean, String… ignoreFields) 把Bean里面的String属性做trim操作。此方法直接对传入的Bean做修改。 |
2.4 ObjectUtil 对象工具类
API文档 对象工具类,包括判空、克隆、序列化等操作。比如一个集合的size为0,我们需要判断它的size才能知道它是不是为空。isEmpty方法就解决了这个问题。
返回类型 | 方法名 |
static T | clone(T obj) 克隆对象 如果对象实现Cloneable接口,调用其clone方法 如果实现Serializable接口,执行深度克隆 否则返回null |
static boolean | contains(Object obj, Object element) 对象中是否包含元素 支持的对象类型包括: String Collection Map Iterator Enumeration Array |
static <T extends CharSequence]]> T | defaultIfBlank(T str, T defaultValue) 如果给定对象为null或者""或者空白符返回默认值 |
static T | defaultIfEmpty(String str, Supplier<? extends T> handle, T defaultValue) 如果给定对象为null或者""返回默认值, 否则返回自定义handle处理后的返回值 |
static boolean | equal(Object obj1, Object obj2) 比较两个对象是否相等。 相同的条件有两个,满足其一即可: obj1 == null && obj2 == null obj1.equals(obj2) 如果是BigDecimal比较,0 == obj1.compareTo(obj2) |
static boolean | hasEmpty(Object… objs) 是否存在null或空对象,通过isEmpty(Object) 判断元素 |
static boolean | hasNull(Object… objs) 是否存在null对象,通过isNull(Object) 判断元素 |
static boolean | isAllEmpty(Object… objs) 是否全都为null或空对象,通过isEmpty(Object) 判断元素 |
static boolean | isEmpty(Object obj) 判断指定对象是否为空,如果为集合,size为0也会认为为空 |
static String | toString(Object obj) 将Object转为String 策略为: |
2.5 时间工具类DateUtil
API文档 日期格式化,日期之间相隔多少天,一天的开始时间结束时间等等
返回类型 | 方法名 |
static int | ageOfNow(String birthDay) 生日转为年龄,计算法定年龄 |
static DateTime | beginOfDay(Date date) 获取某天的开始时间 |
static DateTime | beginOfHour(Date date) 获取某小时的开始时间 |
static DateTime | beginOfMonth(Date date) 获取某月的开始时间 |
static long | betweenDay(Date beginDate, Date endDate, boolean isReset) 判断两个日期相差的天数 |
static long | current() 当前时间的时间戳 |
static DateTime | endOfHour(Date date) 获取某小时的结束时间 |
static String | format(Date date, DateFormat format) 根据特定格式格式化日期 |
static String | formatDateTime(Date date) 格式化日期时间格式 yyyy-MM-dd HH:mm:ss |
static boolean | isAM(Date date) 是否为上午 |
static boolean | isLeapYear(int year) 是否闰年 |
static String | today() 当前日期,格式 yyyy-MM-dd |
static DateTime | tomorrow() 明天 |
static int | year(Date date) 获得年的部分 |
2.6 工具类JSONUtil
API文档 该工具类也是根据阿里的fastjson封装的。
返回类型 | 方法名 |
static JSONArray | createArray() |
static JSONArray | createArray(JSONConfig config)创建 JSONArray |
static boolean | isJson(String str) 是否为JSON字符串,首尾都为大括号或中括号判定为JSON字符串 |
static JSONArray | parseArray(Object arrayOrCollection)JSON字符串转JSONArray |
static JSONObject | parseObj(Object obj) JSON字符串转JSONObject对象此方法会忽略空值,但是对JSON字符串不影响 |
static JSON | readJSON(File file, Charset charset)读取JSON |
static T | toBean(JSON json, Type beanType, boolean ignoreError)转为实体类对象 |
static String | toJsonPrettyStr(Object obj) 转换为格式化后的JSON字符串 |
2.7 工具类JSONObject
API文档
返回类型 | 方法名 |
JSONObject | accumulate(String key, Object value) 积累值。类似于set,当key对应value已经存在时,与value组成新的JSONArray. |
JSONObject | append(String key, Object value) 追加值,如果key无对应值,就添加一个JSONArray,其元素只有value,如果值已经是一个JSONArray,则添加到值JSONArray中。 |
Object | getByPath(String expression) 通过表达式获取JSON中嵌套的对象.表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值 []表达式,可以获取集合等对象中对应index的值 |
JSONObject | increment(String key) 对值加一,如果值不存在,赋值1,如果为数字类型,做加一操作 |
JSONObject | putOnce(String key, Object value) 一次性Put 键值对,如果key已经存在抛出异常,如果键值中有null值,忽略 |
JSONObject | putOpt(String key, Object value) 在键和值都为非空的情况下put到JSONObject中 |
JSONObject | set(String key, Object value) 设置键值对到JSONObject中,在忽略null模式下,如果值为null,将此键移除 |
JSONObject | setDateFormat(String format) 设置转为字符串时的日期格式,默认为时间戳(null值)此方法设置的日期格式仅对转换为JSON字符串有效,对解析JSON为bean无效。 |
2.8 JSONArray
API文档
返回类型 | 方法名 |
JSONArray | put(int index, Object value) 加入或者替换JSONArray中指定Index的值,如果index大于JSONArray的长度,将在指定index设置值,之前的位置填充JSONNull.Null |
JSONArray | setDateFormat(String format) 设置转为字符串时的日期格式,默认为时间戳(null值) |
JSONObject | toJSONObject(JSONArray names) 根据给定名列表,与其位置对应的值组成JSONObject |
List | toList(Class elementType) 转为ArrayList |
String | toString() 转为JSON字符串,无缩进 |
2.9 excel工具类ExcelUtil
API文档 excel工具类引入了第三方的POI,对Excel读取文件流后使用ExcelReader工具对excel进行操作
返回类型 | 方法名 |
static ExcelReader | getReader(File bookFile, int sheetIndex) 获取Excel读取器,通过调用ExcelReader的read或readXXX方法读取Excel内容 |
static ExcelReader | getReader(File bookFile, String sheetName) 获取Excel读取器,通过调用ExcelReader的read或readXXX方法读取Excel内容 |
static ExcelReader | getReader(InputStream bookStream) 获取Excel读取器,通过调用ExcelReader的read或readXXX方法读取Excel内容 默认调用第一个sheet,读取结束自动关闭流 |
ExcelReader
查看Hutool源码中的测试用例了解到,可以读取excel内容并转化为一个bean
@Test
public void excelReadToBeanListTest2() {
ExcelReader reader = ExcelUtil.getReader("f:/test/toBean.xlsx");
reader.addHeaderAlias("姓名", "name");
reader.addHeaderAlias("年龄", "age");
reader.addHeaderAlias("性别", "gender");
List<Person> all = reader.read(0, 2, Person.class);
for (Person person : all) {
Console.log(person);
}
}
当excel中数据量特别大的时候也可以使用Sax的方式进行读取。
ExcelWriter
写入一个bean也是可以的
@Test
public void writeBeanTest() {
List<cn.hutool.poi.excel.TestBean> rows = CollUtil.newArrayList(bean1, bean2);
// 通过工具类创建writer
String file = "e:/writeBeanTest.xlsx";
FileUtil.del(file);
ExcelWriter writer = ExcelUtil.getWriter(file);
// 自定义标题
writer.addHeaderAlias("name", "姓名");
writer.addHeaderAlias("age", "年龄");
writer.addHeaderAlias("score", "分数");
writer.addHeaderAlias("isPass", "是否通过");
writer.addHeaderAlias("examDate", "考试时间");
// 合并单元格后的标题行,使用默认标题样式
writer.merge(4, "一班成绩单");
// 一次性写出内容,使用默认样式
writer.write(rows, true);
// 关闭writer,释放内存
writer.close();
}
之前一直使用阿里的easyExcel,发现hutool中excel相关的工具类也有很多包括Cell工具类、Sheet工具类等等,在实际开发中也可以方便的使用。具体的使用也可以直接看测试用例
2.10集合工具类CollUtil
API文档
返回类型 | 方法名 |
static int | count(Iterable iterable, Matcher matcher) 集合中匹配规则的数量 |
static <K,V> Map<K,V> | createMap(Class<?> mapType) 创建Map传入AbstractMap和Map类将默认创建HashMap |
static <T extends Collection,E> | filter(T collection, Filter filter) 去除指定元素,此方法直接修改原集合 |
static void | forEach(Enumeration enumeration, CollUtil.Consumer consumer) 循环遍历 Enumeration,使用CollUtil.Consumer 接受遍历的每条数据,并针对每条数据做处理 |
static T | getFirst(Iterable iterable) 获取集合的第一个元素 |
static T | getLast(Collection collection) 获取集合的最后一个元素 |
static boolean | hasNull(Iterable<?> iterable) 是否包含null元素 |
static <K,V> HashMap<K,V> | toMap(Iterable<Map.Entry<K,V>> entryIter) 将Entry集合转换为HashMap |
static <K,V> List<Map<K,V>> | toMapList(Map<K,? extends Iterable> listMap) 列转行。将Map中值列表分别按照其位置与key组成新的map。是toListMap(Iterable)的逆方法 |
static <K,V> Map<K,V> | zip(Collection keys, Collection values) 映射键值(参考Python的zip()函数)例如:keys = [a,b,c,d]values = [1,2,3,4]则得到的Map是 {a=1, b=2, c=3, d=4}如果两个数组长度不同,则只对应最短部分 |
3. 总结
以上列出的工具只是冰山一角,具体的使用可以看官方文档,感觉业务系统中的工具类方法基本全覆盖了包括:类型转换、日期时间、IO流相关、系统资源、字符串、Hash算法、URL工具、对像工具、类工具、枚举工具、命令行工具、数字工具、随机工具、唯一ID工具、压缩工具、正则工具、身份证工具、集合、map、文本、图片、网络、加密解密、http客户端、图片验证码等等。学习里面的使用最好先看源码中的测试用例。同时看源码的过程中可以学习别人写的代码。