Java 中節(jié)省 90% 時間的常用的工具類

前言

你們有木有喜歡看代碼的領(lǐng)導(dǎo)啊镶苞,我的領(lǐng)導(dǎo)就喜歡看我寫的代碼,有事沒事就喜歡跟我探討怎么寫才最好,哈哈哈...挺好。

image

今天我們就一起來看看可以節(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):

image-20210719140346416

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ù)ClassLoaderload方法加載數(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)例子中查看到各種用法。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末撒桨,一起剝皮案震驚了整個濱河市查刻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凤类,老刑警劉巖穗泵,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異谜疤,居然都是意外死亡佃延,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門夷磕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來履肃,“玉大人,你說我怎么就攤上這事坐桩〕咂澹” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵绵跷,是天一觀的道長膘螟。 經(jīng)常有香客問我,道長抖坪,這世上最難降的妖魔是什么萍鲸? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮擦俐,結(jié)果婚禮上脊阴,老公的妹妹穿的比我還像新娘。我一直安慰自己蚯瞧,他們只是感情好嘿期,可當(dāng)我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著埋合,像睡著了一般备徐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上甚颂,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天蜜猾,我揣著相機(jī)與錄音秀菱,去河邊找鬼。 笑死蹭睡,一個胖子當(dāng)著我的面吹牛衍菱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播肩豁,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼脊串,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了清钥?” 一聲冷哼從身側(cè)響起琼锋,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎祟昭,沒想到半個月后缕坎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡从橘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年念赶,在試婚紗的時候發(fā)現(xiàn)自己被綠了础钠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恰力。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖旗吁,靈堂內(nèi)的尸體忽然破棺而出踩萎,到底是詐尸還是另有隱情,我是刑警寧澤很钓,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布香府,位于F島的核電站,受9級特大地震影響码倦,放射性物質(zhì)發(fā)生泄漏企孩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一袁稽、第九天 我趴在偏房一處隱蔽的房頂上張望勿璃。 院中可真熱鬧,春花似錦推汽、人聲如沸补疑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽莲组。三九已至,卻和暖如春暖夭,著一層夾襖步出監(jiān)牢的瞬間锹杈,已是汗流浹背撵孤。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留竭望,地道東北人早直。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像市框,于是被迫代替她去往敵國和親霞扬。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容