前言
你們有木有喜歡看代碼的領(lǐng)導(dǎo)啊镶苞,我的領(lǐng)導(dǎo)就喜歡看我寫的代碼,有事沒事就喜歡跟我探討怎么寫才最好,哈哈哈...挺好。
今天我們就一起來看看可以節(jié)省 90% 的加班時間的第三方開源庫吧灶平,第一個介紹的必須是 Apache 下的 Commons 庫。第二個是 google 開源的 Guava 庫箍土。
Apache Commons
Apache Commons 是一個功能非常強(qiáng)大逢享、經(jīng)常被使用到的庫。它有 40 個左右的類庫吴藻,包含了對字符串瞒爬、日期、數(shù)組等的操作。
Lang3
Lang3 是一個處理 Java 中基本對象的包侧但,比如用 StringUtils 類操作字符串矢空、ArrayUtils 類操作數(shù)組、DateUtils 類可以處理日期禀横、MutablePair 類可以返回多個字段等等屁药。
包結(jié)構(gòu):
maven 依賴
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</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");//字符串是不是全是數(shù)字組成酿箭,"." 不算數(shù)字
System.out.println(numeric);
String remove = StringUtils.remove("abcdefgh", "a");//移除字符串
System.out.println(remove);
}
輸出結(jié)果:
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 從當(dāng)前時間開始獲取一周日期
RANGE_WEEK_CENTER 以當(dāng)前日期為中心獲取一周日期
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"));
}
}
輸出結(jié)果:
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
返回多個字段
有時候在一個方法中需要返回多個值的時候缭嫡,經(jīng)常會使用 HashMap 返回或者是 JSON 返回。Lang3 下已經(jīng)幫我們提供了這樣的工具類抬闷,不需要再多寫 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());
}
輸出結(jié)果:
2 這是兩個值
2 這是三個值 Fri Jul 16 15:24:40 CST 2021
Process finished with exit code 0
ArrayUtils 數(shù)組操作
ArrayUtils 是專門處理數(shù)組的類,可以讓方便的處理數(shù)組而不是需要各種循環(huán)操作笤成。
public static void main(String[] args) {
//合并數(shù)組
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 數(shù)組
String[] array4 = ArrayUtils.clone(array3);
System.out.println("array4:"+ArrayUtils.toString(array4));
//數(shù)組是否相同
boolean b = EqualsBuilder.reflectionEquals(array3, array4);
System.out.println(b);
//反轉(zhuǎn)數(shù)組
ArrayUtils.reverse(array4);
System.out.println("array4反轉(zhuǎn)后:"+ArrayUtils.toString(array4));
//二維數(shù)組轉(zhuǎn) 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));
}
}
輸出結(jié)果:
array3:{value1,value2,value3,value4}
array4:{value1,value2,value3,value4}
true
array4反轉(zhuǎn)后:{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);
}
輸出結(jié)果:
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 增強(qiáng)了 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 元素不能加進(jìn)去
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);
}
輸出結(jié)果:
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 統(tǒng)計次數(shù)
用于統(tǒng)計值在集合中出現(xiàn)的次數(shù)壕翩。
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"));
}
輸出結(jié)果:
[2:a,1:b,3:c]
3
Process finished with exit code 0
beanutils Bean 操作
beanutils 是通過反射機(jī)制對 JavaBean 進(jìn)行操作的。比如對 Bean 進(jìn)行復(fù)制傅寡、map 轉(zhuǎn)對象放妈、對象轉(zhuǎn) 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 轉(zhuǎn) map
Map<String, String> describe = BeanUtils.describe(user1);
System.out.println(describe);
//Map 轉(zhuǎn) User
Map<String, String> beanMap = new HashMap();
beanMap.put("name", "張三");
User user3 = new User();
BeanUtils.populate(user3, beanMap);
System.out.println(user3.getName());
}
輸出結(jié)果:
李四
{name=李四}
張三
Process finished with exit code 0
Guava
Google 開源的一個基于 Java 擴(kuò)展項目,包含了一些基本工具芜抒、集合擴(kuò)展珍策、緩存、并發(fā)工具包宅倒、字符串處理等攘宙。
maven 依賴
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1.1-jre</version>
</dependency>
Map<String, List> 類型
在java 代碼中經(jīng)常會遇到需要寫 Map<String, List> map 的局部變量的時候。有時候業(yè)務(wù)情況還會更復(fù)雜一點唉堪。
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("名稱"));
//現(xiàn)在
Multimap<String, String> multimap = ArrayListMultimap.create();
multimap.put("名稱", "張三");
multimap.put("名稱", "李四");
System.out.println(multimap.get("名稱"));
}
輸出結(jié)果:
[張三, 李四]
[張三, 李四]
Process finished with exit code 0
value 不能重復(fù)的 Map
在 Map 中 value 的值時可以重復(fù)的模聋,Guava 可以創(chuàng)建一個 value 不可重復(fù)的 Map肩民,并且 Map 和 value 可以對調(diào)唠亚。
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"));
}
輸出結(jié)果:
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 對調(diào)
biMap = biMap.inverse();
System.out.println(biMap.get("value1"));
}
輸出結(jié)果:
value1
key1
Process finished with exit code 0
Guava cache
寫業(yè)務(wù)的時候肯定會使用緩存持痰,當(dāng)不想用第三方作為緩存的時候灶搜,Map 又不夠強(qiáng)大,就可以使用 Guava 的緩存工窍。
緩存的并發(fā)級別
Guava提供了設(shè)置并發(fā)級別的API
割卖,使得緩存支持并發(fā)的寫入和讀取。與ConcurrentHashMap
類似患雏,Guava cache的并發(fā)也是通過分離鎖實現(xiàn)鹏溯。在通常情況下,推薦將并發(fā)級別設(shè)置為服務(wù)器cpu核心數(shù)淹仑。
CacheBuilder.newBuilder()
// 設(shè)置并發(fā)級別為cpu核心數(shù)丙挽,默認(rèn)為4
.concurrencyLevel(Runtime.getRuntime().availableProcessors())
.build();
緩存的初始容量設(shè)置
我們在構(gòu)建緩存時可以為緩存設(shè)置一個合理大小初始容量,由于Guava的緩存使用了分離鎖的機(jī)制匀借,擴(kuò)容的代價非常昂貴颜阐。所以合理的初始容量能夠減少緩存容器的擴(kuò)容次數(shù)。
CacheBuilder.newBuilder()
// 設(shè)置初始容量為100
.initialCapacity(100)
.build();
設(shè)置最大存儲
Guava Cache可以在構(gòu)建緩存對象時指定緩存所能夠存儲的最大記錄數(shù)量吓肋。當(dāng)Cache中的記錄數(shù)量達(dá)到最大值后再調(diào)用put方法向其中添加對象凳怨,Guava會先從當(dāng)前緩存的對象記錄中選擇一條刪除掉,騰出空間后再將新的對象存儲到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
}
輸出結(jié)果:
null
Process finished with exit code 0
過期時間
expireAfterAccess() 可以設(shè)置緩存的過期時間肤舞。
public static void main(String[] args) throws InterruptedException {
//設(shè)置過期時間為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"));
}
輸出結(jié)果:
value1
null
Process finished with exit code 0
LoadingCache
使用自定義ClassLoader
加載數(shù)據(jù),置入內(nèi)存中均蜜。從LoadingCache
中獲取數(shù)據(jù)時李剖,若數(shù)據(jù)存在則直接返回;若數(shù)據(jù)不存在兆龙,則根據(jù)ClassLoader
的load
方法加載數(shù)據(jù)至內(nèi)存杖爽,然后返回該數(shù)據(jù)敲董。
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;
}
});
}
輸出結(jié)果:
no cache
5
5
6
Process finished with exit code 0
總結(jié)
通過 Apache Commons 和 Guava 兩個第三方的開源工具庫,可以減少循環(huán)慰安、ifelse 的代碼腋寨。寫出的代碼更有健壯性并且可以在新人面前裝一波。Apache Commons 和 Guava 有許許多多的工具類化焕,這里只列出了小小的部分萄窜,可以在官網(wǎng)例子中查看到各種用法。