Java 中节省 90% 时间的常用的工具类

前言

你们有木有喜欢看代码的领导啊,我的领导就喜欢看我写的代码,有事没事就喜欢跟我探讨怎么写才最好,哈哈哈...挺好。
今天我们就一起来看看可以节省 90% 的加班时间的第三方开源库吧,第一个介绍的必须是 Apache 下的 Commons 库。第二个是 google 开源的 Guava 库。

Apache Commons

Apache Commons 是一个功能非常强大、经常被使用到的库。它有 40 个左右的类库,包含了对字符串、日期、数组等的操作。

Lang3

Lang3 是一个处理 Java 中基本对象的包,比如用 StringUtils 类操作字符串、ArrayUtils 类操作数组、DateUtils 类可以处理日期、MutablePair 类可以返回多个字段等等。

包结构:

maven 依赖

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>

字符串操作

对字符串快速操作,在 if else 的少写判空条件。

public static void main(String[] args) {
    boolean blank = StringUtils.isBlank(" ");//注意此处是null哦  这和isEmpty不一样的
    System.out.println(blank);

    boolean empty = StringUtils.isEmpty(" ");//注意这里是false
    System.out.println(empty);

    boolean anyBlank = StringUtils.isAnyBlank("a", " ", "c");// 其中一个是不是空字符串
    System.out.println(anyBlank);

    boolean numeric = StringUtils.isNumeric("1");//字符串是不是全是数字组成,"." 不算数字
    System.out.println(numeric);

    String remove = StringUtils.remove("abcdefgh", "a");//移除字符串
    System.out.println(remove);
}

输出结果:

true
false
true
true
bcdefgh

Process finished with exit code 0

日期操作

终于可以不用 SimpleDateFormat 格式化日期了,DateUtils.iterator 可以获取一段时间。

public static void main(String[] args) throws ParseException {

    Date date = DateUtils.parseDate("2021-07-15", "yyyy-MM-dd");

    Date date1 = DateUtils.addDays(date, 1);//加一天
    System.out.println(date1);

    boolean sameDay = DateUtils.isSameDay(date, new Date());//比较
    System.out.println(sameDay);
    /*
        获取一段日期
        RANGE_WEEK_SUNDAY 从周日开始获取一周日期
        RANGE_WEEK_MONDAY 从周一开始获取一周日期
        RANGE_WEEK_RELATIVE 从当前时间开始获取一周日期
        RANGE_WEEK_CENTER 以当前日期为中心获取一周日期
        RANGE_MONTH_SUNDAY 从周日开始获取一个月日期
        RANGE_MONTH_MONDAY 从周一开始获取一个月日期
        */
    Iterator<Calendar> iterator = DateUtils.iterator(date, DateUtils.RANGE_WEEK_CENTER);
    while (iterator.hasNext()) {
        Calendar next = iterator.next();
        System.out.println(DateFormatUtils.format(next, "yyyy-MM-dd"));
    }
}

输出结果:

Fri Jul 16 00:00:00 CST 2021
false
2021-07-12
2021-07-13
2021-07-14
2021-07-15
2021-07-16
2021-07-17
2021-07-18

Process finished with exit code 0

返回多个字段

有时候在一个方法中需要返回多个值的时候,经常会使用 HashMap 返回或者是 JSON 返回。Lang3 下已经帮我们提供了这样的工具类,不需要再多写 HashMap 和 JSON 了。

public static void main(String[] args) {

    MutablePair<Integer, String> mutablePair = MutablePair.of(2, "这是两个值");
    System.out.println(mutablePair.getLeft() + "  " + mutablePair.getRight());

    MutableTriple<Integer, String, Date> mutableTriple = MutableTriple.of(2, "这是三个值", new Date());
    System.out.println(mutableTriple.getLeft() + " " + mutableTriple.getMiddle() + " " + mutableTriple.getRight());
}

输出结果:

2  这是两个值
2 这是三个值 Fri Jul 16 15:24:40 CST 2021

Process finished with exit code 0

ArrayUtils 数组操作

ArrayUtils 是专门处理数组的类,可以让方便的处理数组而不是需要各种循环操作。

public static void main(String[] args) {

    //合并数组
    String[] array1 = new String[]{"value1", "value2"};
    String[] array2 = new String[]{"value3", "value4"};
    String[] array3 = ArrayUtils.addAll(array1, array2);
    System.out.println("array3:"+ArrayUtils.toString(array3));

    //clone 数组
    String[] array4 = ArrayUtils.clone(array3);
    System.out.println("array4:"+ArrayUtils.toString(array4));

    //数组是否相同
    boolean b = EqualsBuilder.reflectionEquals(array3, array4);
    System.out.println(b);

    //反转数组
    ArrayUtils.reverse(array4);
    System.out.println("array4反转后:"+ArrayUtils.toString(array4));

    //二维数组转 map
    Map<String, String> arrayMap = (HashMap) ArrayUtils.toMap(new String[][]{
        {"key1", "value1"}, {"key2", "value2"}
    });
    for (String s : arrayMap.keySet()) {
        System.out.println(arrayMap.get(s));
    }
}

输出结果:

array3:{value1,value2,value3,value4}
array4:{value1,value2,value3,value4}
true
array4反转后:{value4,value3,value2,value1}
value1
value2

Process finished with exit code 0

EnumUtils 枚举操作

  • getEnum(Class enumClass, String enumName) 通过类返回一个枚举,可能返回空;
  • getEnumList(Class enumClass) 通过类返回一个枚举集合;
  • getEnumMap(Class enumClass) 通过类返回一个枚举map;
  • isValidEnum(Class enumClass, String enumName) 验证enumName是否在枚举中,返回true或false。
public enum ImagesTypeEnum {
    JPG,JPEG,PNG,GIF;
}
public static void main(String[] args) {
    ImagesTypeEnum imagesTypeEnum = EnumUtils.getEnum(ImagesTypeEnum.class, "JPG");
    System.out.println("imagesTypeEnum = " + imagesTypeEnum);
    System.out.println("--------------");
    List<ImagesTypeEnum> imagesTypeEnumList = EnumUtils.getEnumList(ImagesTypeEnum.class);
    imagesTypeEnumList.stream().forEach(
            imagesTypeEnum1 -> System.out.println("imagesTypeEnum1 = " + imagesTypeEnum1)
    );
    System.out.println("--------------");
    Map<String, ImagesTypeEnum> imagesTypeEnumMap = EnumUtils.getEnumMap(ImagesTypeEnum.class);
    imagesTypeEnumMap.forEach((k, v) -> System.out.println("key:" + k + ",value:" + v));
    System.out.println("-------------");
    boolean result = EnumUtils.isValidEnum(ImagesTypeEnum.class, "JPG");
    System.out.println("result = " + result);
    boolean result1 = EnumUtils.isValidEnum(ImagesTypeEnum.class, null);
    System.out.println("result1 = " + result1);
}

输出结果:

imagesTypeEnum = JPG
--------------
imagesTypeEnum1 = JPG
imagesTypeEnum1 = JPEG
imagesTypeEnum1 = PNG
imagesTypeEnum1 = GIF
--------------
key:JPG,value:JPG
key:JPEG,value:JPEG
key:PNG,value:PNG
key:GIF,value:GIF
-------------
result = true
result1 = false

Process finished with exit code 0

collections4 集合操作

commons-collections4 增强了 Java 集合框架,提供了一系列简单的 API 方便操作集合。

maven 依赖

<dependency>  
    <groupId>org.apache.commons</groupId>  
    <artifactId>commons-collections4</artifactId>  
    <version>4.4</version>  
</dependency> 

CollectionUtils 工具类

这是一个工具类,可以检查 null 元素不被加入集合,合并列表,过滤列表,两个列表的并集、差集、合集。有部分功能在 Java 8 中可以被 Stream API 替换。

public static void main(String[] args) {

    //null 元素不能加进去
    List<String> arrayList1 = new ArrayList<>();
    arrayList1.add("a");
    CollectionUtils.addIgnoreNull(arrayList1, null);
    System.out.println(arrayList1.size());

    //排好序的集合,合并后还是排序的
    List<String> arrayList2 = new ArrayList<>();
    arrayList2.add("a");
    arrayList2.add("b");

    List<String> arrayList3 = new ArrayList<>();
    arrayList3.add("c");
    arrayList3.add("d");
    System.out.println("arrayList3:" + arrayList3);

    List<String> arrayList4 = CollectionUtils.collate(arrayList2, arrayList3);
    System.out.println("arrayList4:" + arrayList4);

    //交集
    Collection<String> strings = CollectionUtils.retainAll(arrayList4, arrayList3);
    System.out.println("arrayList3和arrayList4的交集:" + strings);

    //并集
    Collection<String> union = CollectionUtils.union(arrayList4, arrayList3);
    System.out.println("arrayList3和arrayList4的并集:" + union);

    //差集
    Collection<String> subtract = CollectionUtils.subtract(arrayList4, arrayList3);
    System.out.println("arrayList3和arrayList4的差集:" + subtract);

    // 过滤,只保留 b
    CollectionUtils.filter(arrayList4, s -> s.equals("b"));
    System.out.println(arrayList4);
}

输出结果:

1
arrayList3:[c, d]
arrayList4:[a, b, c, d]
arrayList3和arrayList4的交集:[c, d]
arrayList3和arrayList4的并集:[a, b, c, d]
arrayList3和arrayList4的差集:[a, b]
[b]

Process finished with exit code 0

Bag 统计次数

用于统计值在集合中出现的次数。

public static void main(String[] args) {
    Bag bag = new HashBag<String>();
    bag.add("a");
    bag.add("b");
    bag.add("a");
    bag.add("c", 3);
    System.out.println(bag);
    System.out.println(bag.getCount("c"));
}

输出结果:

[2:a,1:b,3:c]
3

Process finished with exit code 0

beanutils Bean 操作

beanutils 是通过反射机制对 JavaBean 进行操作的。比如对 Bean 进行复制、map 转对象、对象转 Map。

maven 依赖

<dependency>
    <groupId>commons-beanutils</groupId>
    <artifactId>commons-beanutils</artifactId>
    <version>1.9.4</version>
</dependency>

public class User {
    
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}
public static void main(String[] args) throws Exception {
    User user1 = new User();
    user1.setName("李四");
    User user2 = (User) BeanUtils.cloneBean(user1);
    System.out.println(user2.getName());

    //User 转 map
    Map<String, String> describe = BeanUtils.describe(user1);
    System.out.println(describe);

    //Map 转 User
    Map<String, String> beanMap = new HashMap();
    beanMap.put("name", "张三");
    User user3 = new User();
    BeanUtils.populate(user3, beanMap);
    System.out.println(user3.getName());
}

输出结果:

李四
{name=李四}
张三

Process finished with exit code 0

Guava

Google 开源的一个基于 Java 扩展项目,包含了一些基本工具、集合扩展、缓存、并发工具包、字符串处理等。

maven 依赖

<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>30.1.1-jre</version>
</dependency>

Map<String, List> 类型

在java 代码中经常会遇到需要写 Map<String, List> map 的局部变量的时候。有时候业务情况还会更复杂一点。

public static void main(String[] args) {
    //以前
    Map<String, List<String>> map = new HashMap<>();
    List<String> list = new ArrayList<>();
    list.add("张三");
    list.add("李四");
    map.put("名称", list);
    System.out.println(map.get("名称"));

    //现在
    Multimap<String, String> multimap = ArrayListMultimap.create();
    multimap.put("名称", "张三");
    multimap.put("名称", "李四");
    System.out.println(multimap.get("名称"));
}

输出结果:

[张三, 李四]
[张三, 李四]

Process finished with exit code 0

value 不能重复的 Map

在 Map 中 value 的值时可以重复的,Guava 可以创建一个 value 不可重复的 Map,并且 Map 和 value 可以对调。

public static void main(String[] args) {
    //会报异常
    BiMap<String ,String> biMap = HashBiMap.create();
    biMap.put("key1", "value");
    biMap.put("key2", "value");
    System.out.println(biMap.get("key1"));
}

输出结果:

Exception in thread "main" java.lang.IllegalArgumentException: value already present: value
    at com.google.common.collect.HashBiMap.put(HashBiMap.java:287)
    at com.google.common.collect.HashBiMap.put(HashBiMap.java:262)
    at org.example.clone.Test.main(Test.java:17)

Process finished with exit code 1
public static void main(String[] args) {
    BiMap<String ,String> biMap = HashBiMap.create();
    biMap.put("key1", "value1");
    biMap.put("key2", "value2");
    System.out.println(biMap.get("key1"));

    //key-value 对调
    biMap = biMap.inverse();
    System.out.println(biMap.get("value1"));
}

输出结果:

value1
key1

Process finished with exit code 0

Guava cache

写业务的时候肯定会使用缓存,当不想用第三方作为缓存的时候,Map 又不够强大,就可以使用 Guava 的缓存。

缓存的并发级别

Guava提供了设置并发级别的API,使得缓存支持并发的写入和读取。与ConcurrentHashMap类似,Guava cache的并发也是通过分离锁实现。在通常情况下,推荐将并发级别设置为服务器cpu核心数。

CacheBuilder.newBuilder()
        // 设置并发级别为cpu核心数,默认为4
        .concurrencyLevel(Runtime.getRuntime().availableProcessors()) 
        .build();

缓存的初始容量设置

我们在构建缓存时可以为缓存设置一个合理大小初始容量,由于Guava的缓存使用了分离锁的机制,扩容的代价非常昂贵。所以合理的初始容量能够减少缓存容器的扩容次数。

CacheBuilder.newBuilder()
        // 设置初始容量为100
        .initialCapacity(100)
        .build();

设置最大存储

Guava Cache可以在构建缓存对象时指定缓存所能够存储的最大记录数量。当Cache中的记录数量达到最大值后再调用put方法向其中添加对象,Guava会先从当前缓存的对象记录中选择一条删除掉,腾出空间后再将新的对象存储到Cache中。

public static void main(String[] args) {
    Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(2).build();
    cache.put("key1", "value1");
    cache.put("key2", "value2");
    cache.put("key3", "value3");
    System.out.println(cache.getIfPresent("key1")); //key1 = null
}

输出结果:

null

Process finished with exit code 0

过期时间

expireAfterAccess() 可以设置缓存的过期时间。

public static void main(String[] args) throws InterruptedException {
    //设置过期时间为2秒
    Cache<String, String> cache1 = CacheBuilder.newBuilder().maximumSize(2).expireAfterAccess(2, TimeUnit.SECONDS).build();
    cache1.put("key1", "value1");
    Thread.sleep(1000);
    System.out.println(cache1.getIfPresent("key1"));
    Thread.sleep(2000);
    System.out.println(cache1.getIfPresent("key1"));
}

输出结果:

value1
null

Process finished with exit code 0

LoadingCache

使用自定义ClassLoader加载数据,置入内存中。从LoadingCache中获取数据时,若数据存在则直接返回;若数据不存在,则根据ClassLoader的load方法加载数据至内存,然后返回该数据。

public class Test {

    public static void main(String[] args) throws Exception {
        System.out.println(numCache.get(1));
        Thread.sleep(1000);
        System.out.println(numCache.get(1));
        Thread.sleep(1000);
        numCache.put(1, 6);
        System.out.println(numCache.get(1));

    }

    private static LoadingCache<Integer, Integer> numCache = CacheBuilder.newBuilder().
            expireAfterWrite(5L, TimeUnit.MINUTES).
            maximumSize(5000L).
            build(new CacheLoader<Integer, Integer>() {
                @Override
                public Integer load(Integer key) throws Exception {
                    System.out.println("no cache");
                    return key * 5;
                }
            });
}

输出结果:

no cache
5
5
6

Process finished with exit code 0

总结

通过 Apache Commons 和 Guava 两个第三方的开源工具库,可以减少循环、ifelse 的代码。写出的代码更有健壮性并且可以在新人面前装一波。Apache Commons 和 Guava 有许许多多的工具类,这里只列出了小小的部分,可以在官网例子中查看到各种用法。

标签: none

已有 4 条评论

  1. 新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com

  2. 2025年10月新盘 做第一批吃螃蟹的人coinsrore.com
    新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
    新车首发,新的一年,只带想赚米的人coinsrore.com
    新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
    做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
    新车上路,只带前10个人coinsrore.com
    新盘首开 新盘首开 征召客户!!!coinsrore.com
    新项目准备上线,寻找志同道合 的合作伙伴coinsrore.com
    新车即将上线 真正的项目,期待你的参与coinsrore.com
    新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
    新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com

  3. 2025年10月新盘 做第一批吃螃蟹的人coinsrore.com
    新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
    新车首发,新的一年,只带想赚米的人coinsrore.com
    新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
    做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
    新车上路,只带前10个人coinsrore.com
    新盘首开 新盘首开 征召客户!!!coinsrore.com
    新项目准备上线,寻找志同道合 的合作伙伴coinsrore.com
    新车即将上线 真正的项目,期待你的参与coinsrore.com
    新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
    新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com

  4. 2025年10月新盘 做第一批吃螃蟹的人coinsrore.com
    新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
    新车首发,新的一年,只带想赚米的人coinsrore.com
    新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
    做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
    新车上路,只带前10个人coinsrore.com
    新盘首开 新盘首开 征召客户!!!coinsrore.com
    新项目准备上线,寻找志同道合 的合作伙伴coinsrore.com
    新车即将上线 真正的项目,期待你的参与coinsrore.com
    新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
    新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com

添加新评论