个人常用 Hutool 工具类 持续更新
技术圈常说一句:“你要会写轮子,也要会用轮子”。工作的时候,为了提升开发效率,节约开发时间,也常常提醒自己不要重复造 “轮子”。
每次开启一个新项目,除了搭建项目必备环境之外,必然要整理一下之前项目沉淀下来的工具类,然后 C V 大法。习惯了一些工具类后,新项目中用不了或是换一下总是感觉缺点什么,再加上每个人都有自己遇到或沉淀的工具类,项目中遇到工具类重复也是很常见的事儿。
话说回来,这些工具类就是开发中必不可少的一种 “轮子”。对于大多数同学,受限于技术,轮子可能勉强写的出来,但是写的是不是够好,够完善,这质量就没法保证了。
谁都是从一开始过来的,但好在有这么一些有志之士,将经年累月写过的轮子反复整理,反复打磨,推出了一个项目,它就是 Hutool。
判断
判断字符串是否为空
String str = " ";
boolean isBlank = StrUtil.isBlank(str); // true
boolean isNotBlank = StrUtil.isNotBlank(str); // false
String str = " ";
boolean isBlank = str == null || str.trim().length() == 0; // true
boolean isNotBlank = str != null && str.trim().length() > 0; // false
判断相等
《阿里巴巴Java开发手册》
【强制】所有整型包装类对象之间值的比较,全部使用 equals 方法比较。
说明:对于 Integer var = ? 在-128 至 127 之间的赋值,Integer 对象是在 IntegerCache.cache 产生, 会复用已有对象,这个区间内的 Integer 值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals 方法进行判断。
// ObjectUtil.equal(o1, o2);
public static boolean equal(Object obj1, Object obj2) {
// 判断是否为 BigDecimal 类型,如果是用 compareTo 比较
// 【强制】BigDecimal 的等值比较应使用 compareTo()方法,而不是 equals()方法。 说明:equals()方法会比较值和精度(1.0 与 1.00 返回结果为 false),而 compareTo() 则会忽略精度。
// 说明:equals()方法会比较值和精度(1.0 与 1.00 返回结果为 false),而 compareTo()则会忽略精度。
if (obj1 instanceof BigDecimal && obj2 instanceof BigDecimal) {
return NumberUtil.equals((BigDecimal) obj1, (BigDecimal) obj2);
}
// 否则使用 Java 官方提供的 Objects 工具类比较
return Objects.equals(obj1, obj2);
}
// Objects.equals(o1, o2);
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
集合操作
集合的出现极大的解决了复杂数据处理的需要,但仅凭 JDK 内置的集合方法,还是略显“苦涩”。
MapUtil
《阿里巴巴Java开发手册》
【推荐】 集合初始化时, 指定集合初始值大小。
说明: HashMap 使用 HashMap(int initialCapacity) 初始化,如果暂时无法确定集合大小, 那么指定默认值( 16) 即可。
正例: initialCapacity = (需要存储的元素个数 / 负载因子) + 1。 注意负载因子(即 loader factor) 默认为 0.75,如果暂时无法确定初始值大小,请设置为 16(即默认值) 。
反例: HashMap 需要放置 1024 个元素,由于没有设置容量初始大小,随着元素增加而被迫不断扩容, resize()方法总共会调用 8 次,反复重建哈希表和数据迁移。当放置的集合元素个数达千万级时会影响程序 性能。
// 判断是否为空、不为空
Map<String, Object> map1 = null;
Map<String, Object> map2 = new HashMap<>();
boolean flag1 = MapUtil.isEmpty(map1); // true
boolean flag2 = MapUtil.isNotEmpty(map1); // false
boolean flag3 = MapUtil.isEmpty(map2); // true
boolean flag4 = MapUtil.isNotEmpty(map2); // false
System.out.println(flag1);
System.out.println(flag2);
System.out.println(flag3);
System.out.println(flag4);
// 快速创建单键值对的 HashMap
HashMap<String, String> map3 = MapUtil.of("CN", "中国");
// 快速创建单键值对的 LinkedHashMap
HashMap<String, String> map4 = MapUtil.of("CN", "中国", true);
// 快速创建指定初始容量大小的 HashMap
HashMap<Object, Object> map5 = MapUtil.newHashMap(2);
// 快速创建LinkedHashMap
HashMap<Object, Object> map6 = MapUtil.newHashMap(true);
// 快速创建指定初始容量大小的 LinkedHashMap
HashMap<Object, Object> map7 = MapUtil.newHashMap(2, true);
// ...
MapUtil 的 newHashMap() 源代码,如下:
/**
* 新建一个HashMap
*
* @param <K> Key类型
* @param <V> Value类型
* @param size 初始大小,由于默认负载因子0.75,传入的size会实际初始大小为size / 0.75 + 1
* @return HashMap对象
*/
public static <K, V> HashMap<K, V> newHashMap(int size) {
return newHashMap(size, false);
}
/**
* 新建一个HashMap
*
* @param <K> Key类型
* @param <V> Value类型
* @param size 初始大小,由于默认负载因子0.75,传入的size会实际初始大小为size / 0.75 + 1
* @param isOrder Map的Key是否有序,有序返回 {@link LinkedHashMap},否则返回 {@link HashMap}
* @return HashMap对象
* @since 3.0.4
*/
public static <K, V> HashMap<K, V> newHashMap(int size, boolean isOrder) {
int initialCapacity = (int) (size / DEFAULT_LOAD_FACTOR) + 1;
return isOrder ? new LinkedHashMap<>(initialCapacity) : new HashMap<>(initialCapacity);
}
CollUtil
map
// List<Long> userIdList = CollUtil.map(userList, UserDO::getId, true);
/**
* 通过func自定义一个规则,此规则将原集合中的元素转换成新的元素,生成新的列表返回<br>
* 例如提供的是一个Bean列表,通过Function接口实现获取某个字段值,返回这个字段值组成的新列表
*
* @param <T> 集合元素类型
* @param <R> 返回集合元素类型
* @param collection 原集合
* @param func 编辑函数
* @param ignoreNull 是否忽略空值,这里的空值包括函数处理前和处理后的null值
* @return 抽取后的新列表
* @since 5.3.5
*/
public static <T, R> List<R> map(Iterable<T> collection, Function<? super T, ? extends R> func, boolean ignoreNull);
UUID 生成器
Hutool 文档
Hutool 重写了 java.util.UUID
的逻辑,对应类为 cn.hutool.core.lang.UUID
,使生成不带-的 UUID 字符串不再需要做字符替换,性能提升一倍左右。
String uuidStr = IdUtil.fastUUID();
System.out.println(uuidStr); // f69c5c5c-73fd-4286-b338-133927789d71
String simpleUuidStr = IdUtil.fastSimpleUUID();
System.out.println(simpleUuidStr); // 6905bc8239c1489a9f6fb18cee1d6884
UUID uuid = UUID.randomUUID();
// 转换为字符串
String uuidStr = uuid.toString();
System.out.println(uuidStr); // 7f4c0b42-d066-4baa-bc24-4d74a69ea78e
// 去除连字符
String replaceUuidStr = uuidStr.replace("-", "");
System.out.println(replaceUuidStr); // 7f4c0b42d0664baabc244d74a69ea78e
程序计时
为了计算程序执行耗时,通常的做法是在程序段前后分别记录一个时间毫秒值变量,然后用结束时间毫秒值减去开始时间毫秒值就可以了。
TimeInterval timer = DateUtil.timer();
// 要计时的程序片段1
// ...
System.out.println("总耗时:" + timer.interval() + "ms");
// 要计时的程序片段2
// ...
System.out.println("总耗时:" + timer.interval() + "ms");
// ...
long startTime = System.currentTimeMillis();
// 要计时的程序片段
// ...
long endTime = System.currentTimeMillis();
System.out.println("总耗时:" + (endTime - startTime) + "ms");