天天看點

Apache Commons包 StringUtils工具類深入整理

字元串是在程式開發中最常見的,Apache Commons開源項目在org.apache.commons.lang3包下提供了StringUtils工具類,該類相當于是對jdk自帶的String類的增強,主要做了幾方面的處理:

1.核心設計理念就是對于null的進行内部處理,使用時不再需要進行繁瑣的null值判定,同時也避免抛出空指針的異常

2.作為工具類,通過增加額外處理的方式,盡量避免抛出異常,例如截取字元串,如指定長度超過了最大長度,不會抛出異常

3.通過更多的重載方法,實作了忽略大小寫、增加控制範圍(左側、右側、中間)等常用操作

4.增加了批量功能,如批量判定、批量比對等(個人認為批量功能适用的場景會比較少)

5.通過對基本功能的綜合應用,增加可直接實作特定開發場景的功能方法

整個工具類經過多年不斷積累,非常龐大,官方按照功能,分了二十幾個大類,方法總數達到了200多個,但其實常用和實用的其實并不沒有那麼多,是以從使用的角度,進行了重新整理,以便更好地利用起來,轉換為開發生産力。

幾個概念先明确下:

1.null:String是引用類型而不是基本類型,是以取值可以為null

2.空串:即不包含任何元素的字元串,表示為""

3.空格:即" ",對應ascii碼是32

4.空白字元:是一組非可見的字元,對于文本處理來說,除了空格外,通常包括tab(\t)、回車(\r)、換行(\n)、垂直制表符(\v)、換頁符(\f),當然,windows系統常用的回車換行的組合(\r\n)也算在其中。

 官方文檔位址:http://commons.apache.org/proper/commons-lang/javadocs/api-3.8.1/index.html

以下是個人根據開發經驗,站在使用者角度,重新整理和歸類。

注:

1.以下整理方法排除掉了官方标記為過時的方法

2.涉及到正規表達式的方法,官方從StringUtils中移除,更換到了RegExUtils類中,不再在StringUtils中展現。

Apache Commons包 StringUtils工具類深入整理

1 判斷與驗證

根據特定規則判斷,不改變字元串自身

1.1判斷是否包含内容

提供了兩類方法,empty類和blank類,差別在對于前者隻有為null或空串時,才傳回true,而後者則會包含所有空白字元(空格、tab、換行、回車等)的判定,使用時需根據要實作的目的來選擇具體用哪一個。

兩大類方法完全類似,隻列出empty類方法

簽名:

public static boolean isEmpty(CharSequence cs)

說明:

隻有為null或空串時,才傳回true

示例:

StringUtils.isEmpty(null); // true

StringUtils.isEmpty("");   // true

擴充:

//判定是否非空串

public static boolean isNotEmpty(CharSequence cs)

//批量判斷,不定數量參數或數組

public static boolean isAnyEmpty(CharSequence... css)

public static boolean isAllEmpty(CharSequence... css)

public static boolean isNoneEmpty(CharSequence... css)

1.2 比較字元串 

基本用法equals、equalsIgnoreCase、compareTo、compareToIgnoreCase,同jdk.

擴充點:

1)擴充equalsAny,可批量進行比對判定,幾乎不會用到,建議使用集合的contains方法更自然。

2)通過compareTo重載函數,可以指定null對象的優先級

1.3 檢驗字元串

通過一系列實作好的方法,來快速傳回是否符合特定規則

//判斷是否隻包含unicode字元(注意:漢字也是unicode字元)

public static boolean isAlpha(CharSequence cs)

//判斷是否隻包含unicode字元及空格

public static boolean isAlphaSpace(CharSequence cs)

//判斷是否隻包含unicode字元及數字

public static boolean isAlphanumeric(CharSequence cs)

//判斷是否隻包含unicode字元、數字及空格

public static boolean isAlphanumericSpace(CharSequence cs)

//判斷是否隻包含數字及空格

public static boolean isNumericSpace(CharSequence cs)

//判斷是否隻包含可列印的ascii碼字元(注意,空格不屬于範圍内)

public static boolean isAsciiPrintable(CharSequence cs)

//判斷是否為數字(注意:小數點和正負号,都會判定為false)

public static boolean isNumeric(CharSequence cs)

//判定是否隻包括空白字元

public static boolean isWhitespace(CharSequence cs)

//判定是否全部為大寫

public static boolean isAllUpperCase(CharSequence cs)

//判定是否全部為小寫

public static boolean isAllLowerCase(CharSequence cs)

//判定是否混合大小寫(注意:包含其他字元,如空格,不影響結果判定)

public static boolean isMixedCase(CharSequence cs)

1.4 包含字元串

contains,同jdk

public static boolean contains(CharSequence seq,int searchChar)

public static boolean contains(CharSequence seq,CharSequence searchSeq)

擴充:

//忽略大小寫

public static boolean containsIgnoreCase(CharSequence str,CharSequence searchStr)

//是否包含空白字元

public static boolean containsWhitespace(CharSequence seq)

//隻包含指定字元

public static boolean containsOnly(CharSequence cs,char... searchChars)

public static boolean containsOnly(CharSequence cs,CharSequence searchChars)

//批量判斷包含任意一個

public static boolean containsAny(CharSequence cs,char... searchChars)

public static boolean containsAny(CharSequence cs,CharSequence searchChars)

//批量判斷不包含任何一個

public static boolean containsNone(CharSequence cs,char... searchChars)

public static boolean containsNone(CharSequence cs,CharSequence searchChars)

1.5 起止字元判定

//startWith

public static boolean startsWith(CharSequence str,CharSequence prefix)

public static boolean startsWithIgnoreCase(CharSequence str,CharSequence prefix)

public static boolean startsWithAny(CharSequence sequence,CharSequence... searchStrings)

//endWith

public static boolean endsWith(CharSequence str,CharSequence suffix)

public static boolean endsWithIgnoreCase(CharSequence str,CharSequence suffix)

public static boolean endsWithAny(CharSequence sequence,CharSequence... searchStrings)

2 處理字元串

不改變字元串實質内容,對首尾以及中間的空白字元進行處理 

2.1 移除空白字元

去除首尾的空白字元,提供了兩類方法,strip類和trim類,

trim類與jdk差異不大,去除包含控制字元(ascii碼<=32)在内的控制字元(底層應用沒做過,有可能會用到控制字元吧),主要是增加了對null的處理。

strip類則做了很多增強,通過重載方法實作了很多其他功能,建議在開發中使用strip類。

注意:全角空格并不在處理範圍内。

簽名:

public static String strip(String str)

擴充:

//去除并轉化為null或empty

public static String stripToNull(String str)

public static String stripToEmpty(String str)

//去除指定字元串

public static String strip(String str,String stripChars)

//控制去除範圍

public static String stripStart(String str,String stripChars)

public static String stripEnd(String str,String stripChars)

//批量操作

public static String[] stripAll(String... strs)

public static String[] stripAll(String[] strs,String stripChars) 

相關方法:

//對字元串基本處理的複合應用,将字元串中所有空白字元去除

public static String deleteWhitespace(String str)

//去除首尾,但中間的空白字元,替換為單個空格

public static String normalizeSpace(String str)

//去除聲調音标,官方舉例是将 \'à\' 轉換為\'a\',很生僻,基本不會用到,不确定漢語拼音的音标是否能處理

public static String stripAccents(String input)

2.2 去除換行

去除結尾的一處換行符,包括三種情況 \r \n \r\n

public static String chomp(String str)

示例

StringUtils.chomp("\r") = ""

StringUtils.chomp("\n") = ""

StringUtils.chomp("\r\n") = ""

StringUtils.chomp("abc \r") = "abc "

StringUtils.chomp("abc\n") = "abc"

StringUtils.chomp("abc\r\n") = "abc"

StringUtils.chomp("abc\r\n\r\n") = "abc\r\n"

StringUtils.chomp("abc\n\r") = "abc\n"

StringUtils.chomp("abc\n\rabc") = "abc\n\rabc"

2.3 去除間隔符

去除末尾一個字元,常見使用場景是通過循環處理使用間隔符拼裝的字元串,去除間隔符

注意:使用時需確定最後一位一定是間隔符,否則有可能破壞正常資料

public static String chop(String str)

示例:

StringUtils.chop("1,2,3,") = "1,2,3"

StringUtils.chop("a") = ""

StringUtils.chop("abc") = "ab"

StringUtils.chop("abc\nabc") = "abc\nab"

//此外,末尾的換行符也視為字元,如果結尾是\r\n,則一塊去除,建議使用專用的chomp,以免造成非預期的結果

StringUtils.chop("\r") = ""

StringUtils.chop("\n") = ""

StringUtils.chop("\r\n") = ""

2.4 去除非數字

去除所有非數字字元,将剩餘的數字字元拼接成字元串

public static String getDigits(String str)

示例:

StringUtils.getDigits("abc") = ""

StringUtils.getDigits("1000$") = "1000"

StringUtils.getDigits("1123~45") = "112345"

StringUtils.getDigits("(541) 754-3010") = "5417543010"

 3.查找字元串

3.1查找字元串 

indexOf與lastIndexOf,可搜尋字元、字元串以及指定起始搜尋位置,同jdk。

public static int indexOf(CharSequence seq,CharSequence searchSeq)

public static int indexOf(CharSequence seq,CharSequence searchSeq,int startPos)

擴充

//增加忽略大小寫控制

public static int indexOfIgnoreCase(CharSequence str,CharSequence searchStr)

//傳回第n次比對的所在的索引數。

public static int ordinalIndexOf(CharSequence str,CharSequence searchStr,int ordinal)

//同時查找多個字元

public static int indexOfAny(CharSequence cs,char... searchChars)

//傳回不在搜尋字元範圍内的第一個索引位置

public static int indexOfAnyBut(CharSequence cs,char... searchChars)

4.編輯字元串

字元串的分割、合并、截取、替換

 4.1 分割字元串 

jdk中的split使用正規表達式比對,而字元串分割最常用場景是如下這種根據間隔符分割

String str="he,ll,o";

String [] reuslt=str.split(",");

雖然split的方式也能實作效果,但是還有有點别扭,而在StringUtils,就是通過字元串比對,而不是正規表達式

//不設定間隔符,預設使用空白字元分割

public static String[] split(String str)

//根據間隔符分割 

public static String[] splitByWholeSeparator(String str,String separator)

//限定傳回,貪婪比對

public static String[] splitByWholeSeparator(String str,String separator,int max),

示例:

StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]

StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]

//空白字元作為一個數組元素傳回(其他方法預設去除空白字元元素)

public static String[] splitPreserveAllTokens(String str) 

示例:

StringUtils.splitPreserveAllTokens("abc def") = ["abc", "def"]

StringUtils.splitPreserveAllTokens("abc def") = ["abc", "", "def"]

StringUtils.splitPreserveAllTokens(" abc ") = ["", "abc", ""]

//特定場景,根據字元類型分割,同一類劃為一個數組元素,駝峰命名情況下,最後一個大寫字母歸屬後面元素而不是前面

public static String[] splitByCharacterTypeCamelCase(String str)

示例:

StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"]

StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"]

StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"]

StringUtils.splitByCharacterTypeCamelCase("number5") = ["number", "5"]

StringUtils.splitByCharacterTypeCamelCase("fooBar") = ["foo", "Bar"]

StringUtils.splitByCharacterTypeCamelCase("foo200Bar") = ["foo", "200", "Bar"]

StringUtils.splitByCharacterTypeCamelCase("ASFRules") = ["ASF", "Rules"]

4.2 合并字元串

jdk使用concat方法,StringUtils使用join,這是一個泛型方法,建議實際使用過程中,還是隻對String使用,不要對數值類型進行合并,會導緻代碼可讀性降低

//預設合并,注意:自動去除空白字元或null元素

public static <T> String join(T... elements)

示例:

StringUtils.join(null) = null

StringUtils.join([]) = ""

StringUtils.join([null]) = ""

StringUtils.join(["a", "b", "c"]) = "abc"

StringUtils.join([null, "", "a"]) = "a"

//使用指定間隔符合并,注意:保留白白字元或null元素

public static String join(Object[] array,char separator)

示例:

StringUtils.join(["a", "b", "c"], \';\') = "a;b;c"

StringUtils.join([null, "", "a"], \';\') = ";;a"

//拼接數值

public static String join(long[] array,char separator)

public static String join(int[] array,char separator)

示例:

StringUtils.join([1, 2, 3], \';\') = "1;2;3"

StringUtils.join([1, 2, 3], null) = "123"

(注意:實測與官網文檔不符,StringUtils.join(new int[]{1, 2, 3}, null);傳回結果是一個很奇怪的字元串[I@77a82f1;使用StringUtils.join(new Object[]{1, 2, 3}, null)),才會傳回期望的“123”

相關方法: 

//joinWith,基本就是把數組參數和間隔符的位置颠倒了一下,意義不大,建議棄用

StringUtils.joinWith(",", {"a", "b"}) = "a,b"

此外,還有大量重載函數,進一步指定起始元素和結束元素,實用性較低,不建議使用。

4.3 截取字元串

相關方法有多個,substring和truncate基本用法同jdk,内部處理異常

public static String substring(String str,int start)

public static String substring(String str,int start,int end)

public static String truncate(String str,int maxWidth);

public static String truncate(String str,int offset,int maxWidth)

擴充:

//直接實作從左側、右側或中間截取指定位數,實用性高

public static String left(String str,int len)

public static String right(String str,int len)

public static String mid(String str,int pos,int len) 

//直接實作特定規則,但總體來說适用場景不多

//截取第一個指定字元前/後的字元串傳回

public static String substringBefore(String str,String separator)

public static String substringAfter(String str,String separator)

//截取最後一個指定字元前/後的字元串傳回

public static String substringBeforeLast(String str,String separator)

public static String substringAfterLast(String str,String separator)

//截取特定字元串中間部分

public static String substringBetween(String str,String tag)

示例:StringUtils.substringBetween("tagabctag", "tag") = "abc"

//傳回起止字元串中間的字元串,且隻傳回第一次比對結果

public static String substringBetween(String str,String open,String close)

//傳回起止字元串中間的字元串,傳回所有比對結果

public static String[] substringBetween(String str,String open,String close)

4.4 替換字元串

jdk中使用replace,StringUtils使用同樣名字,預設替換掉所有比對項,擴充實作了忽略大小寫、隻替換一次、指定最大替換次數等

public static String replace(String text,String searchString,String replacement)

public static String replaceChars(String str,char searchChar,char replaceChar)

擴充:

//忽略大小寫

public static String replaceIgnoreCase(String text,String searchString,String replacement)

//隻替換一次

public static String replaceOnce(String text,String searchString,String replacement)

public static String replaceOnceIgnoreCase(String text,String searchString,String replacement)

//最大替換次數

public static String replace(String text,String searchString,String replacement,int max)

示例:

StringUtils.replace("abaa", "a", "z", 0) = "abaa"

StringUtils.replace("abaa", "a", "z", 1) = "zbaa"

StringUtils.replace("abaa", "a", "z", 2) = "zbza"

StringUtils.replace("abaa", "a", "z", -1) = "zbzz"

注意:

max是替換次數,0代表不做替換,-1代表替換所有,從代碼可讀性考慮,建議按照正常思維模式使用,别使用這些0或者-1比較變态的用法

//擴充批量,過于複雜,執行結果難以預期,不建議使用

public static String replaceEach(String text,String[] searchList,String[] replacementList)

public static String replaceEachRepeatedly(String text,String[] searchList,String[] replacementList)

public static String replaceChars(String str,String searchChars,String replaceChars)

4.5.移除字元串

remove,移除字元

public static String remove(String str,char remove)

public static String remove(String str,String remove)

示例:

StringUtils.remove("queued", "ue") = "qd"

(注意,是第二個參數中所有字元,而不是比對整個字元串)

擴充:

//忽略大小寫

public static String removeIgnoreCase(String str,String remove)

//移除指定位置

public static String removeStart(String str,String remove)

public static String removeEnd(String str,String remove)

//指定位置且忽略大小寫

public static String removeStartIgnoreCase(String str,String remove)

public static String removeEndIgnoreCase(String str,String remove)

 4.6.覆寫部分字元串

public static String overlay(String str,String overlay,int start,int end)

典型應用場景,隐藏字元串如證件号碼、位址或手機号碼中部分字元

示例::

StringUtils.overlay("13712345678","****",3,7)=“137****5678”

注意:實作時做了不少防止異常的處理,比如後面兩個參數為止可以調換,會自動判斷哪個數字小,哪個就是起始值,然後,如果是負數,則表示添加到開始,如果超出字元串自身長度,添加到末尾,但這些奇特的用法盡量避免使用,否則代碼可讀性會很差。

4.7 生成字元串

根據指定資訊産生字元串

public static String repeat(String str,int repeat)

示例:

StringUtils.repeat("a", 3) = "aaa"

StringUtils.repeat("ab", 2) = "abab"

擴充:

//指定間隔符

public static String repeat(String str,String separator,int repeat)

示例

StringUtils.repeat("?", ", ", 3) = "?, ?, ?" 

4.8 字首和字尾

//追加字首,如隻有兩個參數,則是無條件追加,超過兩個參數,是在不比對prefixes任何情況下才追加

public static String prependIfMissing(String str,CharSequence prefix,CharSequence... prefixes)

public static String prependIfMissingIgnoreCase(String str,CharSequence prefix,CharSequence... prefixes)

/追加字尾,如隻有兩個參數,則是無條件追加,超過兩個參數,是在不比對suffixes任何情況下才追加

public static String appendIfMissing(String str,CharSequence suffix,CharSequence... suffixes)

public static String appendIfMissingIgnoreCase(String str,CharSequence suffix,CharSequence... suffixes)

//無條件同時增加字首和字尾

public static String wrap(String str,char wrapWith)

public static String wrap(String str,String wrapWith)

//有條件同時增加字首和字尾

public static String wrapIfMissing(String str,char wrapWith)

public static String wrapIfMissing(String str,String wrapWith)

//去除字首和字尾

public static String unwrap(String str,char wrapChar)

public static String unwrap(String str,String wrapToken)

5.字元串轉換

字元串内容意義不變,形式變化

5.1 大小寫轉換

轉換字元串至大寫或小寫狀态 

//轉換大寫

public static String upperCase(String str)

public static String upperCase(String str,Locale locale)

//轉換小寫

public static String lowerCase(String str)

public static String lowerCase(String str,Locale locale)

//首字母大寫

public static String capitalize(String str)

//首字母小寫

public static String uncapitalize(String str)

//大小寫交換,即大寫變小寫,小寫變大寫

public static String swapCase(String str)

5.2 字元串縮略

将字元串縮減為指定寬度

public static String abbreviate(String str,int maxWidth)

注意,maxWidth必須>=4,否則抛異常

如果字元長度小于maxWidth,直接傳回該字元串,否則縮減效果為 substring(str, 0, max-3) + "..."

示例:

StringUtils.abbreviate("abcdefg", 4) = "a..."

擴充:

//可指定縮減字元的省略符号

public static String abbreviate(String str,String abbrevMarker,int maxWidth)

示例:

StringUtils.abbreviate("abcdefg", "..", 4) = "ab.."

StringUtils.abbreviate("abcdefg", "..", 3) = "a.." 

另有其他重載函數,可指定起始位置,實作..ab..效果,同樣過于複雜,會導緻代碼可讀性變差,不建議使用

5.3 補齊字元串

自動補齊至指定寬度,可指定字元,如不指定,預設補空格,有三個,center、leftPad和rightPad

使用場景:

1)顯示時補充資料寬度一緻使其對齊,更美觀

2)單據流水号,寬度固定,左側補0

public static String center(String str,int size)

public static String center(String str,int size,char padChar)

public static String center(String str,int size,String padStr)

public static String leftPad(String str,int size)

public static String leftPad(String str,int size,char padChar)

public static String leftPad(String str,int size,String padStr)

public static String rightPad(String str,int size)

public static String rightPad(String str,int size,char padChar)

public static String rightPad(String str,int size,String padStr) 

5.4 旋轉字元串

//shift大于0則右旋,小于0則左旋

public static String rotate(String str,int shift)

示例:

StringUtils.rotate("abcdefg", 2) = "fgabcde"

StringUtils.rotate("abcdefg", -2) = "cdefgab"

//完全颠倒字元串順序

public static String reverse(String str)

//颠倒字元串順序,以間隔符為機關進行,單個元素内部不颠倒位置

public static String reverseDelimited(String str,char separatorChar) 

示例:

StringUtils.reverseDelimited("a.bc.d",\'.\')=“d.bc.a”

5.5 編碼轉換

//将位元組數組轉換為指定編碼的字元串

public static String toEncodedString(byte[] bytes,Charset charset)

應用場景:系統間互動時,字元編碼不一緻,如對方傳遞的參數編碼為GB2312,我方編碼為UTF-8,可通過該方法進行轉換

//轉換unicode位碼

public static int[] toCodePoints(CharSequence str)

6 其他

難以歸類的一些功能性方法

6.1 取字元串長度

public static int length(CharSequence cs)

6.2.計算比對次數

public static int countMatches(CharSequence str,CharSequence sub)

public static int countMatches(CharSequence str,char ch)

6.3 預設值處理

//擷取預設字元串,null及空格将會傳回“”,其他情況傳回原始字元串

public static String defaultString(String str)

//擷取預設字元串,第一個參數為null及空格将會傳回第二個參數指定值,其他情況傳回原始字元串

public static String defaultString(String str,String defaultStr)

//其他處理,如果為空白或空,傳回指定值

public static <T extends CharSequence> T defaultIfBlank(T str,T defaultStr)

public static <T extends CharSequence> T defaultIfEmpty(T str,T defaultStr)

//其他處理,傳回數組中第一個不為空白或不為空的元素

public static <T extends CharSequence> T firstNonBlank(T... values)

public static <T extends CharSequence> T firstNonEmpty(T... values) 

6.4.字元串差異

//傳回字元串差異部分,實用性差,不建議使用

public static String difference(String str1,String str2)

//傳回字元串差異的索引位置

public static int indexOfDifference(CharSequence cs1,CharSequence cs2)

public static int indexOfDifference(CharSequence... css)

6.5 取字元串相同字首

public static String getCommonPrefix(String... strs)

示例:

StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab"