2021-05-11

求求你了昏翰,不要再自己實現這些邏輯了筑舅,java開源工具類不香嗎?

下文主要分享這幾個方向的常用工具類:


字符串相關工具類

Java 中 String 應該是日常用的最多一個類吧,平常我們很多代碼需要圍繞 String 尚揣,做一些處理。

JDK 提供 String API 雖然比較多掖举,但是功能比較基礎惑艇,通常我們需要結合 String 多個方法才能完成一個業(yè)務功能。

下面介紹一下 Apache 提供的一個工具類 StringUtils.

Maven Pom 信息如下:

? ? org.apache.commons? ? commons-lang3? ? 3.10復制代碼

commons-lang 有兩個版本,一個是 commons-lang3 滨巴,一個是 commons-lang 思灌。

commons-lang 是老版本,已經很久沒有維護了恭取。

commons-lang3 是一直在維護的版本泰偿,推薦直接使用這個版本。

注意:如果你系統(tǒng)已經有 commons-lang蜈垮,注意如果直接替換成 commons-lang3耗跛,將會編譯錯誤。commons-lang3 中相關類與 commons-lang 一樣攒发,但是包名不一樣调塌。

判斷字符串是否為空

判斷字符串是否為空,想必每個人應該都寫過吧:

if(null == str || str.isEmpty()) {}復制代碼

雖然這段代碼非常簡單惠猿,但是說實話羔砾,阿粉以前還是在這里犯過空指針的異常的。

使用 StringUtils 偶妖,上面代碼可以替換下面這樣:

if(StringUtils.isEmpty(str)) {}復制代碼

StringUtils 內部還有一個方法 isBlank姜凄,也是用來判斷字符串是否為空,兩個方法比較相近趾访,比較搞混态秧,主要區(qū)別如下:

// 字符串固定長度 8位,若不足扼鞋,往左補 0StringUtils.leftPad("test", 8,"0");復制代碼

判斷字符串是否為空申鱼,使用頻率非常高,這里大家可以使用 IDEA Prefix 的功能云头,輸入直接生成判空語句润讥。

字符串固定長度

這個通常用于字符串需要固定長度的場景,比如需要固定長度字符串作為流水號盘寡,若流水號長度不足楚殿,,左邊補 0 竿痰。

這里當然可以使用 String#format 方法脆粥,不過阿粉覺得比較麻煩,這里可以這樣使用:

//?字符串固定長度 8位影涉,若不足变隔,往左補?0StringUtils.leftPad("test",?8,"0");復制代碼

另外還有一個 StringUtils#rightPad,這個方法與上面方法正好相反。

字符串關鍵字替換

StringUtils 提供一些列的方法蟹倾,可以替換某些關鍵字:

// 默認替換所有關鍵字StringUtils.replace("aba","a","z")? ="zbz";// 替換關鍵字匣缘,僅替換一次StringUtils.replaceOnce("aba","a","z")? ="zba";// 使用正則表達式替換StringUtils.replacePattern("ABCabc123","[^A-Z0-9]+","")? ="ABC123"猖闪;....復制代碼

字符串拼接

字符串拼接是個常見的需求,簡單辦法使用 StringBuilder 循環(huán)遍歷拼接:

String[] array = new String[]{"test","1234","5678"};StringBuilder stringBuilder = new StringBuilder();for(String s : array) {? ? stringBuilder.append(s).append(";");}// 防止最終拼接字符串為空if(stringBuilder.length() > 0) {? ? stringBuilder.deleteCharAt(stringBuilder.length() - 1);}System.out.println(stringBuilder.toString());復制代碼

上面業(yè)務代碼不太難肌厨,但是需要注意一下上面這段代碼非常容易出錯培慌,容易拋出 StringIndexOutOfBoundsException。

這里我們可以直接使用以下方法獲取拼接之后字符串:

StringUtils.join(["a","b","c"],",")????="a,b,c"復制代碼

StringUtils 只能傳入數組拼接字符串柑爸,不過我比較喜歡集合拼接吵护,所以再推薦下 Guava 的 Joiner。

實例代碼如下:

String[] array = new String[]{"test","1234","5678"};List list=new ArrayList<>();list.add("test");list.add("1234");list.add("5678");StringUtils.join(array,",");// 逗號分隔符表鳍,跳過 nullJoiner joiner=Joiner.on(",").skipNulls();joiner.join(array);joiner.join(list);復制代碼

字符串拆分

有字符串拼接馅而,就會有拆分字符串的需求,同樣的 StringUtils 也有拆分字符串的方法譬圣。

StringUtils.split("a..b.c",'.')? = ["a","b","c"]StringUtils.splitByWholeSeparatorPreserveAllTokens("a..b.c",".")= ["a","","b","c"]復制代碼

ps:注意以上兩個方法區(qū)別瓮恭。

StringUtils 拆分之后得到是一個數組,我們可以使用 Guava 的

Splitter splitter = Splitter.on(",");// 返回是一個 List 集合厘熟,結果:[ab, , b, c]splitter.splitToList("ab,,b,c");// 忽略空字符串屯蹦,輸出結果 [ab, b, c]splitter.omitEmptyStrings().splitToList("ab,,b,c")復制代碼

StringUtils 內部還有其他常用的方法,小伙伴可以自行查看其 API盯漂。

日期相關工具類

DateUtils/DateFormatUtils

JDK8 之前,Java 只提供一個 Date 類笨农,平常我們需要將 Date 按照一定格式轉化成字符串就缆,我們需要使用 SimpleDateFormat。

SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// Date 轉 字符串simpleDateFormat.format(new Date());// 字符串 轉 DatesimpleDateFormat.parse("2020-05-07 22:00:00");復制代碼

代碼雖然簡單谒亦,但是這里需要注意 SimpleDateFormat竭宰,不是線程安全的,多線程環(huán)境一定要注意使用安全份招。

這里阿粉推薦commons-lang3下的時間工具類DateUtils/DateFormatUtils,解決 Date 與字符串轉化問題切揭。

ps:吐槽一下,你們工程中有沒有多個叫 DateUtils 類锁摔?阿粉發(fā)現我們現有工程廓旬,多個模塊有提供這個類,每個實現大同小異谐腰。

使用方法非常簡單:

// Date 轉化為字符串DateFormatUtils.format(new Date(),"yyyy-MM-dd HH:mm:ss");// 字符串 轉 DateDateUtils.parseDate("2020-05-07 22:00:00","yyyy-MM-dd HH:mm:ss");復制代碼

除了格式轉化之外孕豹,DateUtils 還提供時間計算的相關功能。

Date now = new Date();// Date 加 1 天Date addDays = DateUtils.addDays(now, 1);// Date 加 33 分鐘Date addMinutes = DateUtils.addMinutes(now, 33);// Date 減去 233 秒Date addSeconds = DateUtils.addSeconds(now, -233);// 判斷是否 Wie 同一天boolean sameDay = DateUtils.isSameDay(addDays, addMinutes);// 過濾時分秒,若 now 為 2020-05-07 22:13:00 調用 truncate 方法以后// 返回時間為 2020-05-07 00:00:00Date truncate = DateUtils.truncate(now, Calendar.DATE);復制代碼

JDK8 時間類

JDK8 之后十气,Java 將日期與時間分為 LocalDate励背,LocalTime,功能定義更加清晰砸西,當然其也提供一個 LocalDateTime叶眉,包含日期與時間址儒。這些類相對于 Date 類優(yōu)點在于,這些類與 String 類一樣都是不變類型衅疙,不但線程安全莲趣,而且不能修改。

ps:仔細對比 mysql 時間日期類型 DATE炼蛤,TIME妖爷,DATETIME,有沒有感覺差不多

現在 mybatis 等 ORM 框架已經支持 LocalDate 與 JDBC 時間類型轉化理朋,所以大家可以直接將時間字段實際類型定義為 JDK8 時間類型絮识,然后再進行相關轉化。

如果依然使用的是 Date 類型嗽上,如果需要使用新的時間類型次舌,我們需要進行相關轉化。兩者之間進行轉化兽愤, 稍微復雜一點彼念,我們需要顯示指定當前時區(qū)。

Date now = new Date();// Date-----> LocalDateTime 這里指定使用當前系統(tǒng)默認時區(qū)LocalDateTimelocalDateTime = now.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();// LocalDateTime------> Date 這里指定使用當前系統(tǒng)默認時區(qū)Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());復制代碼

接下來我們使用 LocalDateTime 進行字符串格式化浅萧。

// 按照 yyyy-MM-dd HH:mm:ss 轉化時間LocalDateTime dateTime = LocalDateTime.parse("2020-05-07 22:34:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));// 將 LocalDateTime 格式化字符串String format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(dateTime);復制代碼

另外我們使用 LocalDateTime 獲取當前時間年份咬清,月份特別簡單:

LocalDateTime now = LocalDateTime.now();// 年int year = now.getYear();// 月int month = now.getMonthValue();// 日int day = now.getDayOfMonth();復制代碼

最后我們還可以使用 LocalDateTime 進行日期加減,獲取下一天的時間:

LocalDateTime now = LocalDateTime.now();// 當前時間加一天LocalDateTime plusDays = now.plusDays(1l);// 當前時間減一個小時LocalDateTime minusHours = now.minusHours(1l);// 還有很多其他方法復制代碼

總之 JDK8 提供的時間類非常好用民逼,還沒用過小伙伴霍殴,可以嘗試下。

集合/數組相關

集合與數組我們日常也需要經常使用帝簇,也需要對其進行判空:

if(null == list || list.isEmpty()) {}復制代碼

ps: 數組徘郭、Map 集合與其類似

上面代碼如字符串判空一樣寫起來都非常簡單,但是也比較容易寫出會拋出空指針異常的代碼丧肴。這里我們可以使用commons-collections提供工具類残揉。

pom 信息:

? ? org.apache.commons? ? commons-collections4? ? 4.4復制代碼

ps: 還有一個低版本的 ,artifactId 為 commons-collections

我們可以使用 CollectionUtils/MapUtils進行判空判斷芋浮。

// List/Set 集合判空if(CollectionUtils.isEmpty(list)){}// Map 等集合進行判空if(MapUtils.isEmpty(map)) {? ? }復制代碼

至于數組判空判斷需要使用 commons-lang 下的 ArrayUtils進行判斷:

// 數組判空if(ArrayUtils.isEmpty(array)) {? ? }復制代碼

除此之外還有一些列的對于集合增強方法抱环,比如快速將數組加入到現有集合中:

List listA = new ArrayList<>();listA.add("1");listA.add("2");listA.add("3");String[] arrays = new String[]{"a","b","c"};CollectionUtils.addAll(listA, arrays);復制代碼

其他方法感興趣同學可以再自行研究下,另外 Guava 中也有提供對于集合的操作增強類 Lists/Maps,這個可以看下阿粉之前寫的:老司機阿粉帶你玩轉 Guava 集合類纸巷。

I/O 相關

JDK 有提供一系列的類可以讀取文件等江醇,不過阿粉覺得那些類有些晦澀難懂,實現一個小功能可能還要寫好多代碼何暇,而且還不一定能寫對陶夜。

阿粉推薦一下 Apache 提供的 commons-io 庫,增強 I/O 操作裆站,簡化操作難度条辟。pom 信息:

? ? commons-io? ? commons-io? ? 2.6復制代碼

FileUtils-文件操作工具類

文件操作工具類提供一系列方法黔夭,可以讓我們快速讀取寫入文件。

快速實現文件/文件夾拷貝操作 ,FileUtils.copyDirectory/FileUtils.copyFile

// 拷貝文件File fileA = new File("E:\\test\\test.txt");File fileB = new File("E:\\test1\\test.txt");FileUtils.copyFile(fileA,fileB);復制代碼

使用 FileUtils.listFiles 獲取指定文件夾上所有文件

// 按照指定文件后綴如java,txt等去查找指定文件夾的文件File directory = new File("E:\\test");FileUtils.listFiles(directory, new String[]{"txt"},false);復制代碼

使用 FileUtils.readLines 讀取該文件所有行羽嫡。

// 讀取指定文件所有行 不需要使用while循環(huán)讀取流了List lines = FileUtils.readLines(fileA)復制代碼

有讀就存在寫本姥,可以使用 FileUtils.writeLines,直接將集合中數據杭棵,一行行寫入文本婚惫。

// 可以一行行寫入文本List lines = new ArrayList<>();.....FileUtils.writeLines(lines)復制代碼

IOUtils-I/O 操作相關工具類

FileUtils 主要針對相關文件操作,IOUtils 更加針對底層 I/O,可以快速讀取 InputStream魂爪。實際上 FileUtils 底層操作依賴就是 IOUtils先舷。

IOUtils可以適用于一個比較試用的場景,比如支付場景下滓侍,HTTP 異步通知場景蒋川。如果我們使用 JDK 原生方法寫:

從 Servlet 獲取異步通知內容

byte[] b = null;ByteArrayOutputStream baos = null;String respMsg = null;try {? ? byte[] buffer = new byte[1024];? ? baos = new ByteArrayOutputStream();? // 獲取輸入流? ? InputStreamin= request.getInputStream();for(int len = 0; (len = in.read(buffer)) > 0; ) {? ? ? ? baos.write(buffer, 0, len);? ? }? ? b = baos.toByteArray();? ? baos.close();? // 字節(jié)數組轉化成字符串? ? String reqMessage = new String(b,"utf-8");} catch (IOException e) {? } finally {if(baos != null) {? ? ? ? try {? ? ? ? ? ? baos.close();? ? ? ? } catch (IOException e) {? ? ? ? ? ? ? ? ? }? ? }}復制代碼

上面代碼說起來還是挺復雜的。不過我們使用 IOUtils撩笆,一個方法就可以簡單搞定:

// 將輸入流信息全部輸出到字節(jié)數組中byte[] b = IOUtils.toByteArray(request.getInputStream());// 將輸入流信息轉化為字符串String resMsg = IOUtils.toString(request.getInputStream());復制代碼

ps: InputStream 不能被重復讀取

計時

編程中有時需要統(tǒng)計代碼的的執(zhí)行耗時捺球,當然執(zhí)行代碼非常簡單,結束時間與開始時間相減即可夕冲。

long start = System.currentTimeMillis();? //獲取開始時間//其他代碼//...long end = System.currentTimeMillis(); //獲取結束時間System.out.println("程序運行時間: "+ (end - start) +"ms");復制代碼

雖然代碼很簡單氮兵,但是非常不靈活,默認情況我們只能獲取 ms 單位歹鱼,如果需要轉換為秒泣栈,分鐘,就需要另外再計算醉冤。

這里我們介紹 Guava Stopwatch 計時工具類秩霍,借助他統(tǒng)計程序執(zhí)行時間篙悯,使用方式非常靈活蚁阳。

commons-lang3 與 Spring-core 也有這個工具類,使用方式大同小異鸽照,大家根據情況選擇螺捐。

// 創(chuàng)建之后立刻計時,若想主動開始計時Stopwatch stopwatch = Stopwatch.createStarted();// 創(chuàng)建計時器矮燎,但是需要主動調用 start 方法開始計時// Stopwatch stopwatch = Stopwatch.createUnstarted();// stopWatch.start();// 模擬其他代碼耗時TimeUnit.SECONDS.sleep(2l);// 當前已經消耗的時間System.out.println(stopwatch.elapsed(TimeUnit.SECONDS));;TimeUnit.SECONDS.sleep(2l);// 停止計時 未開始的計時器調用 stop 將會拋錯 IllegalStateExceptionstopwatch.stop();// 再次統(tǒng)計總耗時System.out.println(stopwatch.elapsed(TimeUnit.SECONDS));;// 重新開始定血,將會在原來時間基礎計算,若想重新從 0開始計算诞外,需要調用 stopwatch.reset()stopwatch.start();TimeUnit.SECONDS.sleep(2l);System.out.println(stopwatch.elapsed(TimeUnit.SECONDS));復制代碼

輸出結果為:

246復制代碼

總結

今天介紹了字符串澜沟、日期、數組/集合峡谊、I/O茫虽、計時等工具類刊苍,簡化日常業(yè)務代碼。大家看完可以嘗試一下濒析,不得不說正什,這些工具類真香!

作者:java夢想口服液

鏈接:https://juejin.cn/post/6844904151759978510

來源:掘金

著作權歸作者所有号杏。商業(yè)轉載請聯系作者獲得授權婴氮,非商業(yè)轉載請注明出處。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末盾致,一起剝皮案震驚了整個濱河市主经,隨后出現的幾起案子,更是在濱河造成了極大的恐慌绰上,老刑警劉巖旨怠,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異蜈块,居然都是意外死亡鉴腻,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門百揭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來爽哎,“玉大人,你說我怎么就攤上這事器一】涡浚” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵祈秕,是天一觀的道長渺贤。 經常有香客問我,道長请毛,這世上最難降的妖魔是什么志鞍? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮方仿,結果婚禮上固棚,老公的妹妹穿的比我還像新娘。我一直安慰自己仙蚜,他們只是感情好此洲,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著委粉,像睡著了一般呜师。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贾节,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天汁汗,我揣著相機與錄音趟紊,去河邊找鬼。 笑死碰酝,一個胖子當著我的面吹牛霎匈,可吹牛的內容都是我干的。 我是一名探鬼主播送爸,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼铛嘱,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了袭厂?” 一聲冷哼從身側響起墨吓,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎纹磺,沒想到半個月后帖烘,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡橄杨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年秘症,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片式矫。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡乡摹,死狀恐怖,靈堂內的尸體忽然破棺而出采转,到底是詐尸還是另有隱情聪廉,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布故慈,位于F島的核電站板熊,受9級特大地震影響,放射性物質發(fā)生泄漏察绷。R本人自食惡果不足惜干签,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望克婶。 院中可真熱鬧筒严,春花似錦丹泉、人聲如沸情萤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽筋岛。三九已至,卻和暖如春晒哄,著一層夾襖步出監(jiān)牢的瞬間睁宰,已是汗流浹背肪获。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留柒傻,地道東北人孝赫。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像红符,于是被迫代替她去往敵國和親青柄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內容

  • 前言 不過最近 Review 代碼的時候预侯,咸魚君發(fā)現之前的有些代碼有些繁瑣致开,現在看來, 可以用一些開源工具類實現,...
    碼哥說閱讀 877評論 2 18
  • 一些Java常用的開源工具類萎馅,使用他們不僅可以避免繁瑣的代碼邏輯双戳,還可以避免失誤引發(fā)的錯誤。 幾個方向的常用工具類...
    longLiveData閱讀 308評論 0 0
  • 學習一門語言糜芳,是需要付出大量精力的 昨天大概看了2個小時視頻學習飒货,發(fā)現只聽他講和跟著他操作是很難把知識轉化為自己所...
    Notyes閱讀 127評論 0 1
  • 今天感恩節(jié)哎,感謝一直在我身邊的親朋好友峭竣。感恩相遇膏斤!感恩不離不棄。 中午開了第一次的黨會邪驮,身份的轉變要...
    迷月閃星情閱讀 10,564評論 0 11
  • 彩排完莫辨,天已黑
    劉凱書法閱讀 4,217評論 1 3