Commons-lang記錄:
一個最常用的工具,作為jdk的補充,有必要看一下源碼~~
篇章1——package:lang.*
Lang.*下有很多Utils類,提供了若干static方法供調用,涵蓋了字符串操作、字符操作、JVM交互操作、歸類、異常和位域校驗等等。
首先看看字符串處理類StringUtils
全部的靜態方法,StringUtils繼承自Object。屬于null safe操作。何謂null safe,就是遇到是null的string對象,也會quietly的把它處理掉,而不會有NullPointerException異常,如果有這個異常,那么就是該類的bug了~~
看看StringUtils的各種方法對比吧
比較一下isEmpty和isBlank這兩個方法。isEmpty在判斷” “這樣的字符串時返回的是false,而isBlank返回的是true。這就明顯了吧,empty只對null和””有效,而blank對” ”也有效~~
Clean方法和trim方法都封裝了String的trim方法,唯一的不同是clean將null處理為””,而trim將null處理為null。
以Strip開頭的一系列方法基本可以看做trim方法的擴展,但是更強大的是可以處理前導和后續的各種stripChars,不局限于空白符了。
Equal系列的方法加入了null的判斷,如果都是null那么也返回true。
IndexOf與String的indexOf類似,加入了null的判斷而已,且多了一個ordinalIndexOf方法,可以找到第n個字符串出現的位置。還有一個indexOfIgnoreCase可以不考慮大小寫的判斷位置匹配。實際代碼是調用了string的regionMatches方法,只不過在ignorecase參數上選擇了true。
Contains的實現是一樣的,只是加入了null的判斷。剩下的indexOfAny和containsAny方法都很不錯,完成了集合的匹配~~都包含一個字符數組的參數,可以檢測字符串中是否包含字符數組中的任意個元素,算法沒有特殊的地方,復雜度O(MN)吧~~相比較而言,contains系列的containsOnly和containsNone我倒是覺得更有用一些。
Substring系列的方法,除了substring封裝了string的substring完成了null safe的檢查外,還加入了left、right和mid方法。顧名思義,left可以得到最左邊的若干個字符作為字串,其實就是調用了str.substring(0, len);而right同樣是調用了str.substring(str.length() - len);另外還有一些比如substringBefore和substringAfter之類的,用法類似。substringBetween可以找到兩個字串中間的子串。
Split是值得說道的一個改動,原本大量封裝string的方法,split是個例外,大家知道,string的split方法用到的參數是一個正則式,雖然強大,但是有時候容易出錯。而且string并沒有提供簡化版本。StringUtils提供的split改變了這一狀況,開始使用完整的字符串作為參數,而不是regex。同時,對類似功能的jdk版本的StringTokenizer,在內部方法splitWorker中有段注釋:Direct code is quicker than StringTokenizer.也就是說,這個是更快的一個工具了~~
對于split的反向操作join,用到了一個lang.text包下的StrBuilder類。主要實現即將若干個object數組一個個的append到buffer中。然后最后toString就好。
Delete和remove可以用來刪除string中的內容,比如deleteSpaces可以除去字符串中的所有空白字符(" "t"r"n"b");remove更強大,可以removeStart(只匹配開頭)和removeEnd(只匹配結尾),當然remove可以刪掉字符串中的任意字串。
Replace,同理這里的replace不像string中的一樣是基于正則的,用起來更簡單。而且有replaceOnce和replaceEach等各種用法。還有一個輔助的overlay方法,可以直接替換~~
Chomp和chop我覺得是比較雞肋的一個功能了,去除字符串的最后一個字符或者尾部串,這功能很必要么?
Repeat將已有字符串復制n次。
Pad是一個很有意思的方法,可以將一個已有字符串擴展n個大小,并且填充特定的字符。比如StringUtils.rightPad("bat", 5, 'z') = "batzz"。Pad調用了string的concat方法。
Case conversion的操作就不用多講了,upper和lower都是一樣的。補充說的是,capitalize系列的方法真的很貼心。
補充一個容易讓人誤會的方法——countMatches,記錄一個字符串str中某串sub出現的次數。為什么容易誤會,“aaaa”中有多少“aa”呢?用該方法得到的答案是2~~~大家懂的
Is打頭的一系列方法都非常強大,可以判斷字符串是否符合某種格式,比如isAlpha判斷是否都是字母,isNumeric判斷是否都是數字等等等等。
Reverse這個功能出來后,最先想到的是當初筆試面試時候的一堆回文字符串翻轉之類的考試都要囧了。
Abbreviate方法我覺得是相當實用的一個方法封裝,我們在各種應用中都很常見的“一堆文字……”就是這個方法的最好應用。
Difference方法返回兩個字符串的不同處,可以說是返回第二個字符串的第一個不同的位置開始的子串。indexOfDifference返回不同處的位置。
getCommonPrefix這個方法也很好,可以找到一組字符串的公共前綴。當然只是調用了indexOfDifference這個方法。
接著就是ArrayUtils了
ArrayUtils是一個對數組進行特殊處理的類。當然jdk中的Arrays是有一些功能的,Array也提供了一些動態訪問java數組的方法,這里的ArrayUtils擴展提供了更多的功能。
第一個可以說的方法是toMap方法,該方法就是將一個二維數組轉換為一個HashMap。當然對輸入的參數要求比較嚴格,會拋出各種異常。NullToEmpty方法是一個防御性編程方法的代表,將null的數組直接變為一個空(長度為0)的數組。Subarray方法提供了基于拷貝的子數組生成方法。Reverse方法提供了一個數組翻轉的算法實現。indexOf方法是一個查找指定對象的線性數組查找方法。還提供了一系列裝箱拆箱方法(toPrimitive和toObject),就是將Integer之類的對象類型變成int,反之亦然。addAll方法提供了基于數組拷貝的數組合并,就是將數組1和數組2合并為一個新的數組返回。當然,add方法雖然只添加了一個元素,但是也是要數組拷貝的(數組的效率啊!!!)。同樣的原理,remove(刪除)方法也是基于數組拷貝的,以指定刪除元素為界,分別兩次拷貝它前后的子數組。
再來就是一些補充了
把一些看到的有意思的可能有用的接口方法提取出來。
RandomStringUtils類里有一個random方法,可以產生一個固定長度的隨機字符串。用到了java.util.Random。其中的注釋中提到了對Unicode中沒法處理的surrogate的處理方法。如果不幸隨機到那個位置(D800-DBFF, DC00-DFFF),那么算法中將進行count補充,即提供一次重新隨機的機會。
另外一個比較有趣的類是StopWatch,這是一個秒表類,通過start方法開始計時,通過split方法截斷每一次的分段計時,suspend方法可以暫停秒表,resume恢復計時。最后stop后可以通過getTime獲得總共計時。當然在split后的分段計時可以用getSplitTime獲取。技術實現上就是定義了幾個狀態,然后通過每次狀態的轉變和系統時間的差來表達計時效果。
參考資料:
http://commons.apache.org/lang/userguide.html