java 中节省 90% 时间的常有的工具类

大家好,我是指北君。

我的好朋友小 B 又又又被上司踢了一 jio,这次是因为写的代码太烂了。上司说可以用第三方库类快速实现的方法,小 B 不听还在坚持使用原生代码。

下面一起来看看可以节省 90% 的加班时间的第三方开源库吧。第一个介绍的必须是 Apache 下的 Commons 库,第二个是 google 开源的 Guava 库。

Apache Commons

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

Lang3

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

字符串操作

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

1
2
3
4
5
6
7
8
9

StringUtils.isBlank(" "); //是不是空字符串

StringUtils.isAnyBlank("a", "", "c"); // 其中一个是不是空字符串

StringUtils.isNumeric("1"); //字符串是不是全是数字组成,"." 不算数字

StringUtils.remove("sgsgsdfasd", "a") //移除字符串

日期操作

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Date date = DateUtils.parseDate("2021-07-01", "yyyy-MM-dd");

DateUtils.addDays(date,1);//加一天

DateUtils.isSameDay(date, new Date());//比较

/*
获取一段日期
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"));
}
返回多个字段

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

1
2
3
4
5
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());
ArrayUtils 数组操作

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//合并数组
String[] array1 = new String[]{"value1", "value2"};
String[] array2 = new String[]{"value3", "value4"};
String[] array3 = ArrayUtils.addAll(array1, array2);

//clone 数组
String[] array4 = ArrayUtils.clone(array3);

//数组是否相同
EqualsBuilder.reflectionEquals(array3, array4);

//toString 
ArrayUtils.toString(array4)

//反转数组
ArrayUtils.reverse(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));
}

collections4 集合操作

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

maven 依赖

1
2
3
4
5
<dependency>  
    <groupId>org.apache.commons</groupId>  
    <artifactId>commons-collections4</artifactId>  
    <version>4.4</version>  
</dependency>  
CollectionUtils 工具类

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//null 元素不能加进去
List<String> arrayList1 = new ArrayList<String>();
arrayList1.add("a");
CollectionUtils.addIgnoreNull(arrayList1, null);
System.out.println(arrayList1.size());

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

List<String> arrayList3 = new ArrayList<String>();

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

// 过滤,只保留 b
CollectionUtils.filter(arrayList4, new Predicate<String>() {
    public boolean evaluate(String s) {
        if( s.equals("b")) {
            return true;
        }
        return false;
    }
});

//交集
CollectionUtils.retainAll(arrayList4, arrayList3);

//并集
CollectionUtils.union(arrayList4, arrayList3

//差集
CollectionUtils.subtract(arrayList4, arrayList3)
Bag 统计次数

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

1
2
3
4
5
6
Bag bag = new HashBag<String>();
bag.add("a");
bag.add("b");
bag.add("a");
bag.add("c", 3);
System.out.println(bag.getCount("a"));

beanutils Bean 操作

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

maven 依赖

1
2
3
4
5
<dependency>
    <groupId>commons-beanutils</groupId>
    <artifactId>commons-beanutils</artifactId>
    <version>1.9.4</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//Bean
public class User {
    private String name;
    //省略get/set
}

//copy Bean
User user1 = new User();
user1.setName("李四");
User user2 = (User) BeanUtils.cloneBean(user1);
System.out.println(user2.getName());

//Bean 转 map
BeanUtils.describe(user1);

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

Guava

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

maven 依赖

1
2
3
4
5
<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>30.1.1-jre</version>
</dependency>

Map<String, List> 类型

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

1
2
3
4
5
6
7
8
9
10
11
12
13
//以前
Map<String, List<String>> map = new HashMap<String,List<String>>();
List<String> list = new ArrayList<String>();
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("名称"));

value 不能重复的 Map

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

1
2
3
4
5
6
7
8
9
//会报异常
BiMap<String ,String> biMap = HashBiMap.create();
biMap.put("key1", "value");
biMap.put("key2", "value");
System.out.println(biMap.get("key1"));

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

缓存

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

使用 CacheBuilder.newBuilder().build() 构建缓存,maximumSize() 方法可以设置缓存的存储数量

1
2
3
4
5
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
过期时间

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

1
2
3
4
Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(2).expireAfterAccess(1, TimeUnit.SECONDS).build();
cache.put("key1", "value1");
Thread.sleep(1000);
System.out.println(cache.getIfPresent("key1"));
加载数据

当需要访问 key1 时,如果 key1 此时没有被缓存,就会从回调函数中加载 key1 的值。值得一提的时当多个线程同时访问的时候只有一个线程会执行回调函数。

1
2
3
4
5
6
 cache.get("key1", new Callable<String>() {
    public String call() throws Exception {
        return "value1";
    }
});
System.out.println(cache.getIfPresent("key1"));

Guava 有许许多多的工具类,这里只列出了小小的部分,可以在官网例子中查看到各种用法。

总结

通过 Apache Commons 和 Guava 两个第三方的开源工具库,可以让减少循环、ifelse 的代码。写出的代码更有健壮性并且可以在新人面前装一波。

我是指北君,操千曲而后晓声,观千剑而后识器。感谢各位人才的:点赞、收藏和评论,我们下期更精彩!

Java Geek Tech wechat
欢迎订阅 Java 技术指北,这里分享关于 Java 的一切。