String split方法與Guava Splitter用法區別
今天同事寫了一段使用String split方法的代碼,如下所示,同事期望得到的是字符"1",但是沒想到卻得到空字符。
String targetStr = "1";
String[] splitStrs = targetStr.split("//|");
for (String spiltStr : splitStrs) {
System.out.println(spiltStr);
}
同事修改成如下代碼,可得到的結果也不正確
String[] splitStrs = targetStr.split("|");
對這個問題我也不算特別清楚,因此只好先建議同事修改為如下代碼,修改后同事獲得了正確的結果
final Iterable<String> stringIterable = Splitter.on("|").split(targetStr);
其實問題出在split方法的入參上,查閱String split方法可知道入參其實是一個正則表達式
/* @param regex
* the delimiting regular expression
*
* @return the array of strings computed by splitting this string
* around matches of the given regular expression
*
* @throws PatternSyntaxException
* if the regular expression's syntax is invalid
*
* @see java.util.regex.Pattern
*
* @since 1.4
* @spec JSR-51
*/
public String[] split(String regex) {
return split(regex, 0);
}
既然入參是正則表達式,那就應該用正則表達式去進行解答,在正則表達式中"|"代表的含義是或,因此之前的"//|"應當理解成為匹配字符中存在"//"或空字符,並按匹配進行分割。當按照空字符進行分割是,則得到的就是空字符與"1"了,並且將"//|"修改為"|"也無法糾正錯誤,仍然是按空字符進行分割。這里同事犯了兩個錯誤:
- 錯用了轉義字符,應當使用""而不是"/"
- 誤解了split方法的入參,沒有意識到這是一個正則表達式
所以想要獲得正確的結果,可以使用以下幾種寫法
String[] splitStrs1 = targetStr.split("\\|");
String[] splitStrs2 = targetStr.split("[|]");
String[] splitStrs3 = targetStr.split(Pattern.quote("|"));
那么為何Guava Splitter能夠獲得正確的結果呢?還是要從參數入手,從on方法定義可以看出,作為分隔符的入參可以是多種類型的,如下。
public static Splitter on(char separator);
public static Splitter on(final CharMatcher separatorMatcher);
public static Splitter on(final String separator);
@GwtIncompatible("java.util.regex")
public static Splitter on(final Pattern separatorPattern);
on方法的入參可以是單字符、字符串以及正則表達式,最大程度地保證了使用者不會因為沒有檢查入參含義而導致誤用的問題,從易用性和友好程度角度出發,Guava的大多數方法確實更有優勢,用Splitter實現上述代碼,如下。
final Iterable<String> splits1 = Splitter.on('|').split(targetStr);
final Iterable<String> splits2 = Splitter.on("|").split(targetStr);
final Iterable<String> splits3 = Splitter.on(new CharMatcher() {
@Override
public boolean matches(char c) {
return c == '|';
}
}).split(targetStr);
final Iterable<String> splits4 = Splitter.on(Pattern.compile("\\|")).split(targetStr);