1. 程式人生 > >StringTokenizer、split、substring對比

StringTokenizer、split、substring對比

對String進行分割,JDK提供了三種方法:分別是 java.lang.Stringsplit方法和substring方法,以及java.util.StringTokenizer類.

最常用的就String自帶的兩種方法,StringTokenizer極為少見.

下面就來對比下這三種的用法,分析下優缺點.

在此事先宣告,本文程式碼示例基於JDK1.8_102.

JDK1.6的substring方法有缺陷,在大量使用大量頻繁使用substring的時候會造成嚴重的效能問題,1.7+已修復,故本文一些結論在1.6並不適用.

1.用法介紹

1.1 split方法

split是基於正則表示式的字串分割,一共有兩個過載方法: split(String regex)

split(String regex, int limit).

相信很多人在使用時,通常就是簡單的使用 split(String regex),對 split(String regex, int limit) 很少有了解.實際上 split(String regex) 是呼叫了 split(regex, 0) 來進行的實現.

我們就來詳細的說下 split(String regex, int limit).

對於第一個引數 regex,即所謂的正則表示式字串.但是查看了原始碼我們就會發現,如果 regex是非正則表示式元字元的(指”.$|()[{^?*+\”)單字元字串,或者是長度為2且第一個字元為”\”第二個字元為非數字非大小寫字母的字元時,split

實際上是藉助的substring來進行的實現,這樣會有更好的效能上的表現;否則才會使用正則表示式進行匹配.

對於第二個引數 limit,即引數 regex的匹配次數(最多匹配limit-1次,前提limit為正整數),或者說是結果陣列的最大長度(最大長度limit).此引數的可取值可以為包括負數和0在內的任意整數.

假定limit為0時,結果陣列的長度為len,那麼我們將limit的取值範圍劃分下區間如下:

  • 小於0,regex匹配儘可能多的次數,結果陣列的末尾包含空元素
  • 等於0,regex匹配儘可能多的次數,結果陣列的末尾不包含空元素.
  • 大於0小於等於len,regex匹配limit-1次,結果陣列長度為limit
    ,結果陣列的最後一個元素為剩下的尚未進行正則匹配的字串.
  • 大於len,regex匹配len-1次,結果陣列長度為len,結果陣列的末尾包含空元素

程式碼示例如下:

    String s1 = ";ABBD;;;AS;D;;";
    String[] result;

    //--------------split(regex)-----------------
    result = s1.split(";");
    System.out.print("split(regex)                      基準len:6 結果陣列長度:"+result.length+"  陣列元素: ");
    for(int i = 0;i<result.length;i++){
        System.out.print(i+":"+result[i]+" ");
    }
    System.out.print("\n");


    //--------------split(regex,limit==0)-----------------
    result = s1.split(";",0);
    System.out.print("split(regex,limit==0)    limit:0  基準len:6 結果陣列長度:"+result.length+"  陣列元素: ");
    for(int i = 0;i<result.length;i++){
        System.out.print(i+":"+result[i]+" ");
    }
    System.out.print("\n");

    //--------------split(regex,0<limit<len)
    result = s1.split(";",4);
    System.out.print("split(regex,0<limit<len) limit:4  基準len:6 結果陣列長度:"+result.length+"  陣列元素: ");
    for(int i = 0;i<result.length;i++){
        System.out.print(i+":"+result[i]+" ");
    }
    System.out.print("\n");

    //--------------split(regex,limit==len)-----------------
    result = s1.split(";",6);
    System.out.print("split(regex,limit==len)  limit:6  基準len:6 結果陣列長度:"+result.length+"  陣列元素: ");
    for(int i = 0;i<result.length;i++){
        System.out.print(i+":"+result[i]+" ");
    }
    System.out.print("\n");

    //--------------split(regex,limit<0)-----------------
    result = s1.split(";",-1);
    System.out.print("split(regex,limit<0)     limit:-1 基準len:6 結果陣列長度:"+result.length+"  陣列元素: ");
    for(int i = 0;i<result.length;i++){
        System.out.print(i+":"+result[i]+" ");
    }
    System.out.print("\n");

    //--------------split(regex,limit>len)-----------------
    result = s1.split(";",10);
    System.out.print("split(regex,limit>len)   limit:10 基準len:6 結果陣列長度:"+result.length+"  陣列元素: ");
    for(int i = 0;i<result.length;i++){
        System.out.print(i+":"+result[i]+" ");
    }
    System.out.print("\n");

輸出結果如下:

split(regex)                      基準len:6 結果陣列長度:6  陣列元素: 0: 1:ABBD 2: 3: 4:AS 5:D 
split(regex,limit==0)    limit:0  基準len:6 結果陣列長度:6  陣列元素: 0: 1:ABBD 2: 3: 4:AS 5:D 
split(regex,0<limit<len) limit:4  基準len:6 結果陣列長度:4  陣列元素: 0: 1:ABBD 2: 3:;AS;D;; 
split(regex,limit==len)  limit:6  基準len:6 結果陣列長度:6  陣列元素: 0: 1:ABBD 2: 3: 4:AS 5:D;; 
split(regex,limit<0)     limit:-1 基準len:6 結果陣列長度:8  陣列元素: 0: 1:ABBD 2: 3: 4:AS 5:D 6: 7: 
split(regex,limit>len)   limit:10 基準len:6 結果陣列長度:8  陣列元素: 0: 1:ABBD 2: 3: 4:AS 5:D 6: 7: 

1.2 substring方法

substring方法也有兩個過載的方法:substring(int beginIndex)substring(int beginIndex, int endIndex).

不像大多數過載的方法,substring(int beginIndex) 在實際的實現上並沒有去呼叫 substring(int beginIndex, int endIndex),只是兩者的實現程式碼比較類似.

也不同於splitStringTokenizer類–這兩個都是有近乎標準化的實現,substring通常需要我們自己寫程式碼再進行多次迴圈,反覆的截取才能獲取到想要的結果,所以其效能什麼的,和我們自身的程式碼實現有很大的關係.

以下僅作一個demo:

    String s1 = ";ABBD;;;AS;D;;";
    String subStr = s1;
    List<String> result = new ArrayList<>();
    int index;
    while ((index = subStr.indexOf(";")) >= 0) {
        result.add(subStr.substring(0, index));
        subStr = subStr.substring(index + 1);
    }
    System.out.print("substring                               結果陣列長度:" + result.size() + "  陣列元素: ");
    for (int i = 0; i < result.size(); i++) {
        System.out.print(i + ":" + result.get(i) + " ");
    }
    System.out.print("\n");

輸出結果如下:

substring                               結果陣列長度:7  陣列元素: 0: 1:ABBD 2: 3: 4:AS 5:D 6: 

1.3 StringTokenizer類

StringTokenizer類就很少見到有人使用了,相當生僻的一個類.有java.util包提供.

首先宣告下,StringTokenizer的返回值的每一項被稱為標記(token).

關於其API,可以參見Oracle提供的JDK1.8的 StringTokenizer API,或者也可以參照OSChina提供的JDK1.6中文版的 StringTokenizer API.1.8和1.6相比沒有什麼變化.

其用法也相當的簡單,通過建構函式建立StringTokenizer的例項,然後迴圈獲取結果.

建構函式:

  • StringTokenizer(String str)
  • StringTokenizer(String str, String delim)
  • StringTokenizer(String str, String delim, boolean returnDelims)

第一個引數str即要分割的字串,第二個引數delim即分隔符,預設值" \t\n\r\f"(空白字元、製表符、換行符、回車符和換頁符),第三個引數returnDelims表示分隔符是否作為標記(即token,返回結果的每一項被稱為token)返回.

主要方法:

  • boolean hasMoreTokens() 顧名思義,判斷是否還有未返回的token.
  • String nextToken() 返回字串中的下一個標記
  • String nextToken(String delim) 字串採用指定的delim的下一個標記
  • int countTokens() 返回的是剩餘的標記數

需要注意的是,每呼叫一次nextToken()時,countTokens()的返回值就會減1,也只有在呼叫nextToken()時,才會進行字串的分割.

多餘方法:

  • Object nextElement() 對應 nextToken(),只是返回值型別不同
  • boolean hasMoreElements() 對應 hasMoreTokens()

這兩個方法純粹是為了實現Enumeration介面而加的,可以無視.

用法示例如下:

    String s1 = ";ABBD;;;AS;D;;";
    StringTokenizer stringTokenizer;
    int i = 0;

    stringTokenizer = new StringTokenizer(s1);
    System.out.print("stringtokenizer(str)                      結果陣列長度:" + stringTokenizer.countTokens() + "  陣列元素: ");
    while (stringTokenizer.hasMoreTokens()) {
        System.out.print(i++ + ":"+stringTokenizer.nextToken()+" ");
    }
    System.out.print("\n");

    stringTokenizer = new StringTokenizer(s1, ";");
    System.out.print("stringtokenizer(str,delim)                結果陣列長度:" + stringTokenizer.countTokens() + "  陣列元素: ");
    i = 0;
    while (stringTokenizer.hasMoreTokens()) {
        System.out.print(i++ + ":"+stringTokenizer.nextToken()+" ");
    }
    System.out.print("\n");

    stringTokenizer = new StringTokenizer(s1, ";",false);
    System.out.print("stringtokenizer(str,delim,false)        結果陣列長度:" + stringTokenizer.countTokens() + "  陣列元素: ");
    i = 0;
    while (stringTokenizer.hasMoreTokens()) {
        System.out.print(i++ + ":"+stringTokenizer.nextToken()+" ");
    }
    System.out.print("\n");

    stringTokenizer = new StringTokenizer(s1, ";",true);
    System.out.print("stringtokenizer(str,delim,true)         結果陣列長度:" + stringTokenizer.countTokens() + " 陣列元素: ");
    i = 0;
    while (stringTokenizer.hasMoreTokens()) {
        System.out.print(i++ + ":"+stringTokenizer.nextToken()+" ");
    }
    System.out.print("\n");

輸出結果如下:

stringtokenizer(str)                    結果陣列長度:1  陣列元素: 0:;ABBD;;;AS;D;; 
stringtokenizer(str,delim)              結果陣列長度:3  陣列元素: 0:ABBD 1:AS 2:D 
stringtokenizer(str,delim,false)        結果陣列長度:3  陣列元素: 0:ABBD 1:AS 2:D 
stringtokenizer(str,delim,true)         結果陣列長度:10 陣列元素: 0:; 1:ABBD 2:; 3:; 4:; 5:AS 6:; 7:D 8:; 9:; 

2.返回值對比

我們將前面的三個示例的輸出結果,放到一起對比下:

//s1 = ";ABBD;;;AS;D;;"
split(regex)                      len:6 結果陣列長度:6  陣列元素: 0: 1:ABBD 2: 3: 4:AS 5:D 
split(regex,limit==0)    limit:0  len:6 結果陣列長度:6  陣列元素: 0: 1:ABBD 2: 3: 4:AS 5:D 
split(regex,0<limit<len) limit:4  len:6 結果陣列長度:4  陣列元素: 0: 1:ABBD 2: 3:;AS;D;; 
split(regex,limit==len)  limit:6  len:6 結果陣列長度:6  陣列元素: 0: 1:ABBD 2: 3: 4:AS 5:D;; 
split(regex,limit<0)     limit:-1 len:6 結果陣列長度:8  陣列元素: 0: 1:ABBD 2: 3: 4:AS 5:D 6: 7: 
split(regex,limit>len)   limit:10 len:6 結果陣列長度:8  陣列元素: 0: 1:ABBD 2: 3: 4:AS 5:D 6: 7: 
substring                               結果陣列長度:7  陣列元素: 0: 1:ABBD 2: 3: 4:AS 5:D 6: 
stringtokenizer(str)                    結果陣列長度:1  陣列元素: 0:;ABBD;;;AS;D;; 
stringtokenizer(str,delim)              結果陣列長度:3  陣列元素: 0:ABBD 1:AS 2:D 
stringtokenizer(str,delim,false)        結果陣列長度:3  陣列元素: 0:ABBD 1:AS 2:D 
stringtokenizer(str,delim,true)         結果陣列長度:10 陣列元素: 0:; 1:ABBD 2:; 3:; 4:; 5:AS 6:; 7:D 8:; 9:; 

可以看到,可以說是沒有一個方法的結果是一樣的.

通常情況下,對於字串中的開頭和中間部分的兩個或多個相鄰的分隔符,splitsubstring 都選擇了處理為空字串("")返回,當然substring是我們自己選擇了處理為"",而split是JDK直接處理成為了"".而StringTokenizer則是完全無視.

其實最好還是直接看上面的這個輸出結果的對比,自己再寫寫demo試試,用文字是很難描述清楚的.

3.效能測試

3.1 初步測試

    private static long[] compare(String str) {
    //--------------split(regex)-----------------
    long begin1 = System.nanoTime();
    str.split(";");
    long end1 = System.nanoTime();
    long total1 = end1 - begin1;
    //System.out.println(total1);

    //--------------substring-----------------
    String subStr = str;
    long begin2 = System.nanoTime();
    int index;
    while ((index = subStr.indexOf(";")) >= 0) {
        subStr.substring(0, index);//擷取,獲取結果
        subStr = subStr.substring(index + 1);//獲取剩餘字串
    }
    long end2 = System.nanoTime();
    long total2 = end2 - begin2;
    //System.out.println(total2);

    //--------------substring-----------------
    long begin3 = System.nanoTime();
    StringTokenizer stringTokenizer = new StringTokenizer(str, ";");
    while (stringTokenizer.hasMoreTokens()) {
        stringTokenizer.nextToken();
    }
    long end3 = System.nanoTime();
    long total3 = end3 - begin3;
    //System.out.println(total3);
    return new long[]{total1,total2,total3};
}

/**
 *
 * @param length 構造字串的長度
 * @param times 測試次數
 * @return
 */
private static List<long[]> test(int length,int times) {
    List<long[]> result = new ArrayList<>(times);
    String testStr = RandomStringUtils.random(length, 'a', 'b', 'c', ';');
    while (times-- > 0) {
        result.add(compare(testStr));
    }
    return result;
}

/**
 * 計算平均值.
 * @param list
 * @return
 */
private static List<Long> countAvg(List<long[]> list){
    List<Long> result = new ArrayList<>();
    //因為list中有些值明顯比另外一些大出一個數量級,
    //對平均結果很有影響,故計算平均值時,會先去掉最大的和最小的,儘量保證相對準確
    int size = list.size();
    long t1 = 0;
    long t2 = 0;
    long t3 = 0;
    long[] arr1 = new long[size];
    long[] arr2 = new long[size];
    long[] arr3 = new long[size];
    for(int i = 0;i<size;i++){
        arr1[i] = list.get(i)[0];
        arr2[i] = list.get(i)[1];
        arr3[i] = list.get(i)[2];
    }
    Arrays.sort(arr1);
    Arrays.sort(arr2);
    Arrays.sort(arr3);
    //去掉最大的和最小的
    for(int i = 4;i<size-4;i++){
        t1+=arr1[i];
        t2+=arr2[i];
        t3+=arr3[i];
    }
    //計算平均值
    result.add(t1/(size-8));
    result.add(t2/(size-8));
    result.add(t3/(size-8));
    return result;
}

public static void main(String[] args) {
    int[] lengthArr = {10,100,1_000,10_000,100_000,200_000,300_000};
    int times = 28;
    for(int length : lengthArr){
        System.out.println("---------------------"+length+"---------------------");
        System.out.println(countAvg(test(length,times)));
    }
}

大體上就是先借助org.apache.commons.lang3.RandomStringUtils構建指定長度的字串,然後對這同一個字串做多次(28次)反覆的測試.去掉結果中最大4組和最小4組的結果,剩下的20組結果求了個平均值,儘可能的保證結果的準確.

其中substring就採用前文中的示例的程式碼來做驗證.

結果如下,依次是 splitsubstringstringtokenizer.單位納秒:

---------------------10---------------------
[3801, 577, 1636]
---------------------100---------------------
[12158, 7683, 10682]
---------------------1000---------------------
[43901, 108142, 32689]
---------------------10000---------------------
[263923, 4143798, 108206]
---------------------100000---------------------
[812864, 277557016, 632573]
---------------------200000---------------------
[1524611, 1112681830, 1241102]
---------------------300000---------------------
[2296348, 2526878872, 1853160]

可以看到當字串的長度達到30萬時,splitstringtokenizer的效能並無明顯的差距,而substring的耗時則是已經達到了秒的級別,高出1000倍以上.

但是在字串比較短,可能從測試來看,可能就是在兩三百以內時,substring的效能是完全要優於其它兩者的,但是依舊不是很明顯的差距–畢竟上面的資料的單位是納秒,或者說是百萬分之一毫秒.而可以說99%的情況下我們遇到的字串都不會超過這個長度,所以三種方法用哪種都行,當然從程式碼的簡潔角度來看,優先split.

3.2 長字串測試(長度1000萬以上)

在3.1測試中,由於substring的效能實在是太糟糕(當然也有可能是3.1程式碼中 substring 的測試程式碼寫的有問題,對結果造成了明顯的影響,如果有誰發現請指正),在字串長度30萬的時候,做28次反覆測試累計所需的時間已經達到了1分鐘以上,而splitStringTokenizer尚在微秒級別,所以接下來我們就只針對這兩個做測試.

依舊是3.1的程式碼,稍作修改,測試下長度1000萬以上的字串的效能,直接上結果(字串長度1000萬~1億),單位毫秒:

//單位毫秒,前者為split,後者為StringTokenizer
---------------------10000000---------------------
[92, 60]
---------------------20000000---------------------
[190, 117]
---------------------30000000---------------------
[380, 177]
---------------------40000000---------------------
[935, 235]
---------------------50000000---------------------
[1061, 360]
---------------------60000000---------------------
[1252, 750]
---------------------70000000---------------------
[1688, 792]
---------------------80000000---------------------
[3731, 818]
---------------------90000000---------------------
[2202, 978]
---------------------100000000---------------------
[2295, 1055]

轉換成折線圖如下:

折線圖

比較奇怪的是,反覆測了好幾遍,split都是在長度為八千萬時,耗時最長.在長度超過1億的時候,也有類似的情況,不過從總體來看耗時還是在不斷增長的.

但是依舊不影響結論,也就是說,在分割很長的字串(測試用的是長度超過千萬的字串,實際上在百萬級別左右就應該考慮優先使用StringTokenizer)時,應當優先使用StringTokenizer.

3.3 結論

  1. 在字串長度較短時,也就是我們絕大多數情況下接觸到的,長度在幾十、幾百以內,splitsubstringstringtokenizer 的效能差距是在納秒級別,可隨意選擇.
  2. 在字串長度在幾百以上,幾十萬以下這個級別,選擇使用splitStringTokenizer(substring的耗時比其它兩者要高出一到數個數量級),其中整體來看StringTokenizer效能上略佔優勢,但是由於本身耗時就在1毫秒之內,所以優勢幾乎可以忽略.從程式碼簡潔易讀的角度來看,應當優先採用split.
  3. 在處理很長的字串時,尤其是長度超過百萬甚至是千萬級別,效能的差距已經達到了毫秒級甚至秒級,應當優先選擇StringTokenizer.

需要注意的是,三種方法的返回值是不一樣的,詳情參見前文第二節.

4.題外話:關於JDK不提倡使用StringTokenizer

JDK中關於StringTokenizer的描述中提到,不建議使用這個類來進行字串分割,提倡使用的是 java.lang.Stringsplit方法.

StringTokenizer is a legacy class that is retained for compatibility reasons although its use is discouraged in new code.
It is recommended that anyone seeking this functionality use the split method of String or the java.util.regex package instead.

官方並沒有說明原因.

個人猜測可能是如下原因:

  1. 最主要的原因.substring對於多個分隔符,比如","";""#"等同時做分隔符時,程式碼就會變得相當冗雜.stringtokenizer雖然是支援多個分隔符,但是分隔符必須為單個字元,也就是說,",;#"會被認為是3個單字元的分隔符,但是不能看做一個整體,更別說單字元與多字元的分隔符同時存在的情況.但是split則完全不存在前兩者的問題,由於使用的是正則表示式,所以split支援任何格式、任何數量長度的分隔符.
  2. 在絕大多數場景下,我們處理的都是很短的字串,此時splitStringTokenizer的效能差距可以忽略.
  3. split使用最為簡單,作為String自身提供的方法,直接呼叫就可返回結果,不像其它兩個還需要額外的處理.

既然這樣那JDK為何還要提供StringTokenizer這麼一個實現?主要是因為,Java對正則表示式的支援以及split方法都是在JDK1.4才提供的,而StringTokenizer是作為早期的JDK(從1.0就已經存在了)的一個”臨時性的”分割字串的解決方案.

相關推薦

StringTokenizersplitsubstring對比

對String進行分割,JDK提供了三種方法:分別是 java.lang.String的 split方法和substring方法,以及java.util.StringTokenizer類. 最常用的就String自帶的兩種方法,StringTokenizer極

java java中subStringsplitstringTokenizer三種擷取字串方法的效能比較

面試的時候,string  基本上是必須問的知識   突然想起面試的時候曾經被人問過:都知道在大資料量情況下,使用String的split擷取字串效率很低,有想過用其他的方法替代嗎?用什麼替代?我當時的回答很斬釘截鐵:沒有。 google了一下,發現有2中替代方法,於

Java中substringsplitStringTokenizer三種擷取字串方法的效能比較

最近在閱讀java.lang下的原始碼,讀到String時,突然想起面試的時候曾經被人問過:都知道在大資料量情況下,使用String的split擷取字串效率很低,有想過用其他的方法替代嗎?用什麼替代?我當時的回答很斬釘截鐵:沒有。 Google了一下,發現有2種替代方法,於是

ddsplitcsplit命令

sys /dev/ 上下文 其中 print /tmp 文章 系列文章 還需 本文目錄: 1.1 dd命令 1.2 split命令 1.3 csplit命令 在Linux最常用的文件生成和切片工具是dd,它功能比較全面,但無法以行為單位提取文件數據,也無法直接將文件按大

Linux命令之cutsplitpaste

new cut pass 一行 strong CA swd cat 文件 cut 提取文本並輸出 -d 指定分隔符-c 以字符為單位-f 以d分割後的第幾部分 示例:1 -d 和-f 使用取出以:為分隔符,第2部分的內容[root@mail tmp]#

區分slicesplicesplitjoin方法

關於字串和陣列的方法,我們經常會用到,下面就詳細的區分下slice、splice、split、join方法,加深下記憶並做個筆記。 slice (陣列) 定義和用法 slice()方法提取部分的陣列元素,返回包含提取元素的新陣列,不會改變原陣列。

數組字符串轉換 joinsplittoString

指定 轉換 所有 可用 col code ring 參數 con join 將數組轉換成一個字符串 可用制定符號分割 var arr = [‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘]; var str = arr.join() console.log(str)

String的substringsplit, StringTokenizer 擷取字串效能比較

package com.huawei.jvm.decorater; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; public class MainT

subString() subStr()splice()split()的區別

1.slice(); Array和String物件都有 在Array中 slice(i,[j]) i為開始擷取的索引值,負數代表從末尾算起的索引值,-1為倒數第一個元素 j為結束的索引值,預設時則獲取從i到末尾的所有元素 引數返回: 返回索引值從i到j的陣列,

C#幾種擷取字串的方法(split SubstringReplaceremove)

C#截圖字串常用的方法有 split 、Substring、Replace、remove等。 split的使用:  1. Split( Char ())      返回的字串陣列包含此例項中的子字串(

ListSetMap下各類型的對比

hashtable class ray hashmap 速查 使用 線程同步 highlight ash 1.List和Set: List: 元素有放入順序,元素可重復,查找效率高,插入刪除效率低; Set: 元素無放入順序,元素不可重復,(元素雖然無順序,但元素在Set

項目自動構建工具對比(MavenGradleAnt)

執行 存儲 maven構建 width pil 特點 print 新的 jar Java世界中主要有三大構建工具:Ant、Maven和Gradle。經過幾年的發展,Ant幾乎銷聲匿跡、Maven也日薄西山,而Gradle的發展則如日中天。 Maven的主要功能主要分為5點,

MVCMVPMVVM模式對比總結(2)橫向構架模型

span del nec 處理請求 eth .cn pos 實現 通過 前言說明 在實戰項目及學習中來總結一下Android端項目構架 包括MVC、MVP、MVVM,主要針對移動Android端 該篇只描述橫向構架模型 目錄 1.構架基礎 2.橫向構架模型 3.縱向

kubernetes中porttarget portnode port的對比分析,以及kube-proxy代理

ans toc contain exp red lec adb service 接口 轉:http://blog.csdn.net/xinghun_4/article/details/50492041 容器網絡實例 服務中的3個端口設置 這幾個port的概念很容易混淆,比

CSS字體大小: em與pxpt百分比之間的對比

edi images 渲染 電腦 是的 可讀性 客戶端設置 等於 per CSS樣式最混亂的一個方面是應用程序中文本擴展的font-size屬性。在CSS中,你可以用四個不同的單位度量來顯示在web瀏覽器中的文本大小。這四個單位哪一種最適合Web? 這個問題引起了廣泛的爭論

對比Cassandra MongodbCouchDBRedisRiak MembaseNeo4jHBase

知識 gre 日誌功能 cor phar 大小 pla ebo 在操作 轉自:http://www.cnblogs.com/alephsoul-alephsoul/archive/2013/04/26/3044630.html 導讀:Kristóf Kov&

javascript中substring()slice()substr()方法的區別

start 指定 art bsp ava color 目的 開始 www substring()方法用於提取字符串中介於兩個指定下標之間的字符。 stringObject.substring(start,stop)slice() 方法可提取字符串的某個部分,並以新的字

RabbitMQRedisZeroMQActiveMQKafka/Jafka對比

特性 bytes key cer 記錄 rabbitmq consumer apache target RabbitMQRabbitMQ是使用Erlang編寫的一個開源的消息隊列,本身支持很多的協議:AMQP,XMPP, SMTP, STOMP,也正因如此,它非常重量級

hibernatemybatisspring data 的對比

lec 機制 程序 共享 編寫 .get lis 技術方案 found 轉: 1.概念: Hibernate :Hibernate是一個開放源代碼的對象關系映射框架,它對JDBC進行了非常輕量級的對象封裝,使得Java程序員可以隨心所欲的使用對象編程思維來操縱數據庫。著力點

shell特殊符號,cutsortwcuniqteetrsplit命令

shell特殊符號 cut、sort、wc、uniq、tee、tr、split命令 *代表0個或多個任意字符[root@localhost ~]# ls *txt11.txt 1.txt 22.txt 2.txt aa.txt a.txt ?只代表一個任意字符不管是數字還是字母,只要是一個