org.apache.commons.lang3.StringUtils 源码解读(1)
一、背景
不管是公司的项目,还是个人的日常练习,都会使用 org.apache.commons.lang3.StringUtils 这个String工具类,究其原因,是太好用了,而且太全了。比如判断是否为空,截取,拼接之类的。一直没有仔细的看过它的源码,今天我就研究一番,同时作为我“阅读源码”路上的第一步。
二、常用API
注:本次是基于commons-lang3-3.8.1 进行阅读分析总结的,其他版本与此相差不多。
2.0、概念释义
2.0.1、null,empty,space的区别
null:代表无效数据,调用其他Api会有NPE异常;
empty:是有效数据,表示一个长度为0的字符串——"";
space:是有效数据,表示一个长度不为0,但是没有任何内容的字符串——“ ”,其trim后和empty是等价的;
2.0.2、什么是CharSequence
查看StringUtils的源码,你会发现它的方法参数里面经常会出现一个类型:CharSequence。所以有必要在这里解释一下。
CharSequence是一个描述字符串结构的接口,它的常用方法有length(),charAt(),toString 。很熟悉对吧。它的常见实现类有String,StringBuffer,StringBuilder。只要有字符串就可以为CharSequence实例化。
public interface CharSequence { int length(); char charAt(int index); public String toString();
//字符串截取 CharSequence subSequence(int start,int end);
public default IntStream chars() {
//默认逻辑
}
public default IntStream codePoints() {
//默认逻辑
} }
//String public final class String implements java.io.Serializable, Comparable<String>, CharSequence //StringBuffer public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence //StringBuilder public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence
2.1、Empty
2.1.1、isEmpty:检查字符串是 "" 或 null
//源码 public static boolean isEmpty(final CharSequence cs) { return cs == null || cs.length() == 0; }
@Test public void isEmpty_Test() { //true StringUtils.isEmpty(null); //true StringUtils.isEmpty(""); //false StringUtils.isEmpty(" "); //false StringUtils.isEmpty("bob"); //false StringUtils.isEmpty(" bob "); }
2.1.2、isNotEmpty:与isEmpty正好相反,判断不为""且不为null
//源码 public static boolean isNotEmpty(final CharSequence cs) { return !isEmpty(cs); }
@Test public void isNotEmpty_Test() { //false StringUtils.isNotEmpty(null); //false StringUtils.isNotEmpty(""); //true StringUtils.isNotEmpty(" "); //true StringUtils.isNotEmpty("bob"); //true StringUtils.isNotEmpty(" bob "); }
2.1.3、isAnyEmpty
2.1.4、isNoneEmpty
2.1.5、isAllEmpty
2.2、Blank
2.2.1、isBlank:检查一个字符串是 "",或null,或只有空格
与isEmpty相比,对于“ ”,isEmpty(" ") =false,isBlank(" ") =true,
//源码 public static boolean isBlank(final CharSequence cs) { int strLen; if (cs == null || (strLen = cs.length()) == 0) { return true; } for (int i = 0; i < strLen; i++) { if (!Character.isWhitespace(cs.charAt(i))) { return false; } } return true; }
@Test public void isBlank_Test() { //true StringUtils.isBlank(null); //true StringUtils.isBlank(""); //true StringUtils.isBlank(" "); //false StringUtils.isBlank("bob"); //false StringUtils.isBlank(" bob "); }
2.2.2、isNotBlank:检查一个字符串不是 "",且不是null,且不只有空格
@Test public void isNotBlank_Test() { //false StringUtils.isNotBlank(null); //false StringUtils.isNotBlank(""); //false StringUtils.isNotBlank(" "); //true StringUtils.isNotBlank("bob"); //true StringUtils.isNotBlank(" bob "); }
2.2.3、isAnyBlank
2.2.4、isNoneBlank
2.2.5、isAllBlank
2.3、Trim
2.3.1、trim:移除字符串两端的空字符串
//源码 public static String trim(final String str) { return str == null ? null : str.trim(); }
@Test public void trim_Test() { //null StringUtils.trim(null); //"" StringUtils.trim(""); //"" StringUtils.trim(" "); //"abc" StringUtils.trim("abc"); //"abc" StringUtils.trim(" abc "); }
2.3.2、trimToNull:trim之后,用isEmpty进行了判断,如果true返回null,否则返回trim后的值
//源码 public static String trimToNull(final String str) { final String ts = trim(str); return isEmpty(ts) ? null : ts; }
StringUtils.trimToNull(null) = null StringUtils.trimToNull("") = null StringUtils.trimToNull(" ") = null StringUtils.trimToNull("abc") = "abc" StringUtils.trimToNull(" abc ") = "abc"
2.3.3、trimToEmpty:如果为null,返回“”,否则返回trim后的值
//源码 public static String trimToEmpty(final String str) { return str == null ? EMPTY : str.trim(); }
StringUtils.trimToEmpty(null) = "" StringUtils.trimToEmpty("") = "" StringUtils.trimToEmpty(" ") = "" StringUtils.trimToEmpty("abc") = "abc" StringUtils.trimToEmpty(" abc ") = "abc"
2.4、Truncate
2.4.1、truncate:字符串截取,从索引为0处截取,截取固定的长度
//源码 public static String truncate(final String str, final int maxWidth) { return truncate(str, 0, maxWidth); }
StringUtils.truncate(null, 0) = null StringUtils.truncate(null, 2) = null StringUtils.truncate("", 4) = "" StringUtils.truncate("abcdefg", 4) = "abcd" StringUtils.truncate("abcdefg", 6) = "abcdef" StringUtils.truncate("abcdefg", 7) = "abcdefg" StringUtils.truncate("abcdefg", 8) = "abcdefg" StringUtils.truncate("abcdefg", -1) = throws an IllegalArgumentException
可以看到,对于起始截取索引,截取长度为负数时,直接报异常;然后被截取字符串为null时,返回null;截取索引大于字符串长度时,返回“”。
//源码 public static String truncate(final String str, final int offset, final int maxWidth) { if (offset < 0) { throw new IllegalArgumentException("offset cannot be negative"); } if (maxWidth < 0) { throw new IllegalArgumentException("maxWith cannot be negative"); } if (str == null) { return null; } if (offset > str.length()) { return EMPTY; } if (str.length() > maxWidth) { final int ix = offset + maxWidth > str.length() ? str.length() : offset + maxWidth; return str.substring(offset, ix); } return str.substring(offset); }
StringUtils.truncate(null, 0, 0) = null StringUtils.truncate(null, 2, 4) = null StringUtils.truncate("", 0, 10) = "" StringUtils.truncate("", 2, 10) = "" StringUtils.truncate("abcdefghij", 0, 3) = "abc" StringUtils.truncate("abcdefghij", 5, 6) = "fghij" StringUtils.truncate("raspberry peach", 10, 15) = "peach" StringUtils.truncate("abcdefghijklmno", 0, 10) = "abcdefghij" StringUtils.truncate("abcdefghijklmno", -1, 10) = throws an IllegalArgumentException StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, 10) = "abcdefghij" StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, Integer.MAX_VALUE) = "abcdefghijklmno" StringUtils.truncate("abcdefghijklmno", 0, Integer.MAX_VALUE) = "abcdefghijklmno" StringUtils.truncate("abcdefghijklmno", 1, 10) = "bcdefghijk" StringUtils.truncate("abcdefghijklmno", 2, 10) = "cdefghijkl" StringUtils.truncate("abcdefghijklmno", 3, 10) = "defghijklm" StringUtils.truncate("abcdefghijklmno", 4, 10) = "efghijklmn" StringUtils.truncate("abcdefghijklmno", 5, 10) = "fghijklmno" StringUtils.truncate("abcdefghijklmno", 5, 5) = "fghij" StringUtils.truncate("abcdefghijklmno", 5, 3) = "fgh" StringUtils.truncate("abcdefghijklmno", 10, 3) = "klm" StringUtils.truncate("abcdefghijklmno", 10, Integer.MAX_VALUE) = "klmno" StringUtils.truncate("abcdefghijklmno", 13, 1) = "n" StringUtils.truncate("abcdefghijklmno", 13, Integer.MAX_VALUE) = "no" StringUtils.truncate("abcdefghijklmno", 14, 1) = "o" StringUtils.truncate("abcdefghijklmno", 14, Integer.MAX_VALUE) = "o" StringUtils.truncate("abcdefghijklmno", 15, 1) = "" StringUtils.truncate("abcdefghijklmno", 15, Integer.MAX_VALUE) = "" StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE, Integer.MAX_VALUE) = "" StringUtils.truncate("abcdefghij", 3, -1) = throws an IllegalArgumentException StringUtils.truncate("abcdefghij", -2, 4) = throws an IllegalArgumentException
2.5、Strip
2.5.1、strip
2.5.2、stripToNull
2.5.3、StripToEmpty
2.5.4、stripStart
//null System.out.println(StringUtils.stripStart(null,"xyzbca")); //"" System.out.println(StringUtils.stripStart("","xyzbca")); //"abc " String s1 = StringUtils.stripStart("abc ",null); System.out.println(s1+","+s1.length()); //**abc ** String s2 = StringUtils.stripStart( " abc ",null); System.out.println("**"+s2+"**"); //** abc ** String s3 = StringUtils.stripStart(" abc ",""); System.out.println("**"+s3+"**"); //bc String s4 = StringUtils.stripStart("abc", "a"); System.out.println(s4); //bcysz String s5 = StringUtils.stripStart("xyabcysz","yax"); System.out.println(s5)
//源码 public static String stripStart(final String str, final String stripChars) { int strLen; if (str == null || (strLen = str.length()) == 0) { return str; } int start = 0; if (stripChars == null) { while (start != strLen && Character.isWhitespace(str.charAt(start))) { start++; } } else if (stripChars.isEmpty()) { return str; } else { while (start != strLen && stripChars.indexOf(str.charAt(start)) != -1) { start++; } } return str.substring(start);
}
2.5.5、stripEnd
//源码 public static String stripEnd(final String str, final String stripChars) { int end; if (str == null || (end = str.length()) == 0) { return str; } if (stripChars == null) { while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) { end--; } } else if (stripChars.isEmpty()) { return str; } else { while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) { end--; } } return str.substring(0, end);
}
2.5.6、stripAll
2.5.7、stripAccents
2.6、Equals、toString
2.6.1、equals
2.6.2、equalsIgnoreCase
2.6.3、equalsAny
2.6.4、equalsAnyIgnoreCase
2.6.5、toString
2.6.6、toEncodedString
2.7、Compare
2.7.1、compare
2.7.2、compareIgnoreCase
2.8、IndexOf
2.8.1、indexOf
2.8.2、ordinalIndexOf
2.8.3、indexOfIgnoreCase
2.8.4、lastIndexOf
2.8.5、lastOrdinalIndexOf
2.8.6、lastIndexOfIgnoreCase
2.8.7、indexOfAny
2.8.8、indexOfAnyBut
2.8.9、lastIndexOfAny
2.9、Contains
2.9.1、contains
2.9.2、containsIgnoreCase
2.9.3、containsWhitespace
2.9.4、containsAny
2.9.5、containsOnly
2.9.6、containsNone
2.10、Substring
2.10.1、substring
2.10.2、left
2.10.3、right
2.10.4、mid
2.10.5、substringBefore
2.10.6、substringAfter
2.10.7、substringBeforeLast
2.10.8、substringAfterLast
2.10.9、substringsBetween
2.11、Split
2.11.1、split
2.11.2、splitByWholeSeparator
2.11.3、splitByWholeSeparatorPreserveAllTokens
2.11.4、splitByWholeSeparatorWorker
2.11.5、splitPreserveAllTokens
2.11.6、splitWorker
2.11.7、splitByCharacterType
2.11.8、splitByCharacterTypeCamelCase
2.12、Join
2.12.1、join
2.12.1、joinWith
2.13、Delete
2.13.1、deleteWhitespace
2.14、Remove
2.14.1、remove
2.14.2、removeIgnoreCase
2.14.3、removeStart
2.14.4、removeStartIgnoreCase
2.14.5、removeEnd
2.14.6、removeEndIgnoreCase
2.14.7、removeAll
2.14.8、removeFirst
2.14.9、removePattern
2.15、Replace
2.15.1、replace
2.15.2、replaceIgnoreCase
2.15.3、replaceOnce
2.15.4、replaceOnceIgnoreCase
2.15.5、replacePattern
2.15.6、replaceAll
2.15.7、replaceFirst
2.15.8、replaceEach
2.15.9、replaceEachRepeatedly
2.15.10、replaceChars
2.16、Overlay
2.16.1、overlay
2.17、Chomping
2.17.1、chomp
2.18、Chop
2.18.1、chop
2.19、Repeat
2.19.1、repeat
2.20、Pad
2.20.1、rightPad
2.20.2、leftPad
2.21、Length
2.21.1、length
2.22、Center
2.22.1、center
2.23、Case
2.23.1、upperCase
2.23.2、lowerCase
2.23.3、swapCase
2.24、Capitalize
2.24.1、capitalize
2.24.2、uncapitalize
2.25、CountMatches
2.25.1、countMatches
2.26、判断/检查
2.26.1、isAlpha
2.26.2、isAlphaSpace
2.26.3、isAlphanumeric
2.26.4、isAlphanumericSpace
2.26.5、isAsciiPrintable
2.26.6、isNumeric
2.26.7、isNumericSpace
2.26.8、isWhitespace
2.26.9、isAllLowerCase
2.26.10、isAllUpperCase
2.26.11、isMixedCase
2.27、Default
2.27.1、defaultString
2.27.2、defaultIfBlank
2.27.3、defaultIfEmpty
2.28、Rotate
2.28.1、rotate
2.29、Reverse
2.29.1、reverse
2.29.1、reverseDelimited
2.30、Abbreviate
2.30.1、abbreviate
2.30.2、abbreviateMiddle
2.31、Difference
2.31.1、difference
2.31.2、indexOfDeffererce
2.32、开头/结尾
2.32.1、startsWith
2.32.2、startsWithIgnoreCase
2.32.3、startsWithAny
2.32.4、endsWith
2.32.5、endsWithIgnoreCase
2.32.6、endsWithAny
2.33、追加
2.33.1、appendIfMissing
2.33.2、appendIfMissingIgnoreCase
2.33.3、prependIfMissing
2.33.4、prependIfMissingIgnoreCase
2.34、Wrap
2.34.1、wrap
2.34.2、wrapIfMissing
2.34.3、unwrap
2.35、其他
2.35.1、getCommonPrefix
2.35.2、getLevenshteinDistance
2.35.3、getJaroWinklerDistance
2.35.4、getFuzzyDistance
2.35.5、getDigits
2.35.6、firstNonBlank
2.35.7、firstNonEmpty
2.35.8、normalizeSpace
2.35.9、toCodePoints
在全栈的道路上,积极向上、成熟稳重、谦虚好学、怀着炽热的心向前方的走得更远。