1. 程式人生 > >String.split(),StringTokenizer,StringUtils.split()的原始碼分析與效能比較

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 方式簡便很多。