String.split(),StringTokenizer,StringUtils.split()的原始碼分析與效能比較
他們都是用來對字串進行切割
String.split():
從jdk1.4開始,通過正則表示式進行字串的匹配切割,有可能會丟擲 PatternSyntaxException異常,返回的是切割之後的字串陣列。
String 的split 有兩個過載的方法分別是
-
public String[] split(String regex, int limit) {
-
public String[] split(String regex) { 如果選擇只有regex這個引數的方法,預設會呼叫limit=0的上面的過載方法。 這倆有啥區別呢?看下limit的文件解釋:
The {@code limit} parameter controls the number of times the * pattern is applied and therefore affects the length of the resulting * array. If the limit is greater than zero then the pattern * will be applied at most n-1 times, the array's * length will be no greater than n, and the array's last entry * will contain all input beyond the last matched delimiter. If n * is non-positive then the pattern will be applied as many times as * possible and the array can have any length. If n is zero then * the pattern will be applied as many times as possible, the array can * have any length, and trailing empty strings will be discarded.
首先limit的作用是用來控制切割次數的;
如果n>0,會通過這個pattern 對字串切割n-1次
如果n<0,會通過這個pattern 對字串切割儘可能的多次,有多少切多少。
如果n=0,會通過這個pattern 對字串切割儘可能的多次,但是,如果後面都是空字串的話,會拋棄掉
下面我們debug看一下不同limit的值的切割過程:
檢視split原始碼發現,split是根據regex 通過正則來匹配字串的, 正則表示式必然涉及到regex的編譯,這其實是很耗時的。
StringUtils.split()
StringUtils的split有四個過載方法:
這個是按照空格進行切割的,如果字串為null的話,返回的是null,如果字串為空的話,返回是空陣列。
public static String[] split(final String str) {
return split(str, null, -1);
}
* StringUtils.split(null) = null * StringUtils.split("") = [] * StringUtils.split("abc def") = ["abc", "def"] * StringUtils.split("abc def") = ["abc", "def"] * StringUtils.split(" abc ") = ["abc"]
這個是按照指定的字元進行切割,separatorChar預設為false ,這個不可以指定因為預設呼叫的私有方法splitWorker中引數separatorChar預設已經指定為為false,separatorChar為false表示相鄰的分隔符,作為一個,如果為true,分隔符將被作為空分割符。
public static String[] split(final String str, final char separatorChar) {
return splitWorker(str, separatorChar, false);
}
* StringUtils.split(null, *) = null
* StringUtils.split("", *) = []
* StringUtils.split("a.b.c", '.') = ["a", "b", "c"]
* StringUtils.split("a..b.c", '.') = ["a", "b", "c"]
* StringUtils.split("a:b:c", '.') = ["a:b:c"]
* StringUtils.split("a b c", ' ') = ["a", "b", "c"]
這個是按照指定的字串進行切割,separatorChar預設為false ,注意,如果分隔符為null,則分隔符等同於“ ”
public static String[] split(final String str, final String separatorChars) {
return splitWorker(str, separatorChars, -1, false);
}
* StringUtils.split(null, *) = null
* StringUtils.split("", *) = []
* StringUtils.split("abc def", null) = ["abc", "def"]
* StringUtils.split("abc def", " ") = ["abc", "def"]
* StringUtils.split("abc def", " ") = ["abc", "def"]
* StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
這個是按照指定的字串進行切割,separatorChar預設為false ,注意,如果分隔符為null,則分隔符等同於“ ”,引數max用於指定返回的array中最多包含幾個元素。
public static String[] split(final String str, final String separatorChars, final int max) {
return splitWorker(str, separatorChars, max, false);
}
* StringUtils.split(null, *, *) = null
* StringUtils.split("", *, *) = []
* StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"]
* StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"]
* StringUtils.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"]
* StringUtils.split("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
StringTokenizer
其實看StringUtils的split的原始碼解釋的時候,發現第一句就是
* <p>Splits the provided text into an array, separators specified.
* This is an alternative to using StringTokenizer.</p>
所以說StringUtils 的split 是 StringTokenizer 的替代品。他們的用法完全可以相互實現。
StringTokenizer 有三個過載方法:
這個是按照預設的分隔符進行切割,預設有" \t\n\r\f"
public StringTokenizer(String str) {
this(str, " \t\n\r\f", false);
}
這個是按照指定的分隔符delim進行切割
public StringTokenizer(String str, String delim) {
this(str, delim, false);
}
這個是按照指定的分隔符進行切割,returnDelims 表示是否返回分隔符,並初始化一些引數
public StringTokenizer(String str, String delim, boolean returnDelims) {
currentPosition = 0;
newPosition = -1;
delimsChanged = false;
this.str = str;
maxPosition = str.length();
delimiters = delim;
retDelims = returnDelims;
setMaxDelimCodePoint();
}
下面是StringTokenizer 的demo
所以處於效能考慮呢?
肯定要麼使用StringTokenizer 要麼使用StringUtils
但是如果是我,我肯定選擇StringUtils,因為他倆完全可以相互替代,但是StringUtils 方式簡便很多。