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