亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

String和StringBuffer之概覽

2019-11-18 12:51:42
字體:
來源:轉載
供稿:網友

  String和StringBuffer之概覽
  非可變對象一旦創建之后就不能再被改變,可變對象則可以在創建之后被改變。String對象是非可變對象,StringBuffer對象則是可變對象。為獲得更佳的性能你需要根據實際情況小心謹慎地選擇到底使用這兩者中的某一個。下面的話題會作具體的闡述。(注重:這個章節假設讀者已經具備java的String和StringBuffer的相關基礎知識。)
 
創建字符串的較佳途徑
你可以按照以下方式創建字符串對象:
1. String s1 = "hello"; 
    String s2 = "hello"; 
2. String s3 = new String("hello");
    String s4 = new String("hello");
 
上面哪種方式會帶來更好的性能呢?下面的代碼片斷用來測量二者之間的區別。

StringTest1.java
package com.performance.string;
/** This class shows the time taken for creation of
 *  String literals and String objects.
 */
public class StringTest1 {
public static void main(String[] args){
    // create String literals
    long startTime = System.currentTimeMillis();
    for(int i=0;i<50000;i++){
    String s1 = "hello";
    String s2 = "hello";
    }
    long endTime = System.currentTimeMillis();
    System.out.                  + (endTime - startTime) + " milli seconds" );
    // create String objects using 'new' key
Word       
    long startTime1 = System.currentTimeMillis();
    for(int i=0;i<50000;i++){
    String s3 = new String("hello");
    String s4 = new String("hello");
    }
    long endTime1 = System.currentTimeMillis();
    System.out.println("Time taken for creation of String objects : "
                  + (endTime1 - startTime1)+" milli seconds");
    }
}
這段代碼的輸出:
Time taken for creation of String literals : 0 milli seconds
Time taken for creation of String objects : 170 milli seconds
 
JVM是怎樣處理字符串的呢?
  Java虛擬機會維護一個內部的滯留字符串對象的列表(唯一字符串的池)來避免在堆內存中產生重復的String對象。當JVM從class文件里加載字符串字面量并執行的時候,它會先檢查一下當前的字符串是否已經存在于滯留字符串列表,假如已經存在,那就不會再創建一個新的String對象而是將引用指向已經存在的String對象,JVM會在內部為字符串字面量作這種檢查,但并不會為通過new要害字創建的String對象作這種檢查。當然你可以明確地使用String.intern()方法強制JVM為通過 new要害字創建的String對象作這樣的檢查。這樣可以強制JVM檢查內部列表而使用已有的String對象。
  所以結論是,JVM會內在地為字符串字面量維護一些唯一的String對象,程序員不需要為字符串字面量而發愁,但是可能會被一些通過 new要害字創建的String對象而困擾,不過他們可以使用intern()方法來避免在堆內存上創建重復的String對象來改善Java的運行性能。下一小節會向大家展示更多的信息。
 
下圖展示了未使用intern()方法來創建字符串的情況。
 
string_creating_without_intern() method
  你可以自己使用==操作符和String.equals()方法來編碼測試上面提到的區別。==操作符會返回true假如一些引用指向一個相同的對象但不會判定String對象的內容是否相同;String.equals()方法會返回true假如被操作的String對象的內容相同。對于上面的代碼會有s1==s2,因為s1和s2兩個引用指向同一個對象,對于上面的代碼,s3.equals(s4)會返回true因為兩個對象的內容都一樣為”hello”。你可以從上圖看出這種機制。在這里有三個獨立的包含了相同的內容(”hello”)的對象,實際上我們不需要這么三個獨立的對象—— 因為要運行它們的話既浪費時間又浪費內存。
 
  那么怎樣才能確保String對象不會重復呢?下一個話題會涵蓋對于內建String機制的愛好。
 
滯留字符串的優化作用
  同一個字符串對象被重復地創建是不必要的,String.intern ()方法可以避免這種情況。下圖說明了String.intern()方法是如何工作的,String.intern()方法檢查字符串對象的存在性,假如需要的字符串對象已經存在,那么它會將引用指向已經存在的字符串對象而不是重新創建一個。下圖描繪了使用了intern()方法的字符串字面量和字符串對象的創建情況。
 
string_creating_with_intern() method
下面的例程幫助大家了解String.intern()方法的重要性。
StringTest2.java
 
package com.performance.string;
// This class shows the use of intern() method to improve performance
public class StringTest2 {
public static void main(String[] args){
    // create String references like s1,s2,s3...so on..
    String variables[] = new String[50000];
    for( int i=0;i<variables.length;i++){
        variables[i] = "s"+i;
    }
    // create String literals
    long startTime0 = System.currentTimeMillis();
    for(int i=0;i<variables.length;i++){
        variables[i] = "hello";
    }
    long endTime0 = System.currentTimeMillis();
    System.out.println("Time taken for creation of String literals : "
                         + (endTime0 - startTime0) + " milli seconds" );
    // create String objects using 'new' keyword       
    long startTime1 = System.currentTimeMillis();
    for(int i=0;i<variables.length;i++){
        variables[i] = new String("hello");
    }
    long endTime1 = System.currentTimeMillis();
    System.out.println("Time taken for creation of String objects with 'new' key word : "
                        + (endTime1 - startTime1)+" milli seconds");
    // intern String objects with intern() method   
    long startTime2 = System.currentTimeMillis();
    for(int i=0;i<variables.length;i++){
        variables[i] = new String("hello");
        variables[i] = variables[i].intern();
    }
    long endTime2 = System.currentTimeMillis();
    System.out.println("Time taken for creation of String objects with intern(): "
                        + (endTime2 - startTime2)+" milli seconds");
    }
}
這是上面那段代碼的輸出結果:
Time taken for creation of String literals : 0 milli seconds
Time taken for creation of String objects with 'new' key word : 160 milli seconds
Time taken for creation of String objects with intern(): 60 milli seconds
 
連接字符串時候的優化技巧
  你可以使用+操作符或者String.concat()或者StringBuffer.append()等辦法來連接多個字符串,那一種辦法具有最佳的性能呢?
  如何作出選擇取決于兩種情景,第一種情景是需要連接的字符串是在編譯期決定的還是在運行期決定的,第二種情景是你使用的是 StringBuffer還是String。通常程序員會認為StringBuffer.append()方法會優于+操作符或 String.concat()方法,但是在一些特定的情況下這個假想是不成立的。
 
1) 第一種情景:編譯期決定相對于運行期決定
請看下面的StringTest3.java代碼和輸出結果。

package com.performance.string;
/** This class shows the time taken by string concatenation at compile time and run time.*/
public class StringTest3 {
  public static void main(String[] args){
    //Test the String Concatination
    long startTime = System.currentTimeMillis();
    for(int i=0;i<5000;i++){
    String result = "This is"+ "testing the"+ "difference"+ "between"+
            "String"+ "and"+ "StringBuffer";
    }
    long endTime = System.currentTimeMillis();
    System.out.println("Time taken for string concatenation using + Operator : "
         + (endTime - startTime)+ " milli seconds");
    //Test the StringBuffer Concatination
    long startTime1 = System.currentTimeMillis();
    for(int i=0;i<5000;i++){
    StringBuffer result = new StringBuffer();
         result.append("This is");
        result.append("testing the");
        result.append("difference");
        result.append("between");
       result.append("String");
       result.append("and");
       result.append("StringBuffer");
     }
    long endTime1 = System.currentTimeMillis();
    System.out.println("Time taken for String concatenation using StringBuffer : "
           + (endTime1 - startTime1)+ " milli seconds");
  }
}
這是上面的代碼的輸出結果:
Time taken for String concatenation using + operator : 0 milli seconds
Time taken for String concatenation using StringBuffer : 50 milli seconds
很有趣地,+操作符居然比StringBuffer.append()方法要快,為什么呢?
 
  這里編譯器的優化起了要害作用,編譯器像下面舉例的那樣簡單地在編譯期連接多個字符串。它使用編譯期決定取代運行期決定,在你使用new要害字來創建String對象的時候也是如此。
 
編譯前:
String result = "This is"+"testing the"+"difference"+"between"+"String"+"and"+"StringBuffer";
編譯后:
String result = "This is testing the difference between String and StringBuffer";

這里String對象在編譯期就決定了而StringBuffer對象是在運行期決定的。運行期決定需要額外的開銷當字符串的值無法預先知道的時候,編譯期決定作用于字符串的值可以預先知道的時候,下面是一個例子。
 
編譯前:
public String getString(String str1,String str2) {
    return str1+str2;
}
編譯后:
return new StringBuffer().append(str1).append(str2).toString();
運行期決定需要更多的時間來運行。
 
2) 第二種情景:使用StringBuffer取代String
看看下面的代碼你會發現與情景一相反的結果——連接多個字符串的時候StringBuffer要比String快。
StringTest4.java
 
package com.performance.string;
/** This class shows the time taken by string concatenation
using + operator and StringBuffer  */
public class StringTest4 {
 public static void main(String[] args){
    //Test the String Concatenation using + operator
    long startTime = System.currentTimeMillis();
    String result = "hello";
    for(int i=0;i<1500;i++){
        result += "hello";
    }
    long endTime = System.currentTimeMillis();
    System.out.println("Time taken for string concatenation using + operator : "
                  + (endTime - startTime)+ " milli seconds");
    //Test the String Concatenation using StringBuffer
    long startTime1 = System.currentTimeMillis();
    StringBuffer result1 = new StringBuffer("hello");
    for(int i=0;i<1500;i++){
        result1.append("hello");
    }
    long endTime1 = System.currentTimeMillis();
    System.out.println("Time taken for string concatenation using StringBuffer :  "
                  + (endTime1 - startTime1)+ " milli seconds");
    }
}
這是上面的代碼的輸出結果:
Time taken for string concatenation using + operator : 280 milli seconds
Time taken for String concatenation using StringBuffer : 0 milli seconds
看得出StringBuffer.append()方法要比+操作符要快得多,為什么呢?

  原因是兩者都是在運行期決定字符串對象,但是+操作符使用不同于StringBuffer.append()的規則通過String和StringBuffer來完成字符串連接操作。(譯注:什么樣的規則呢?)
 
借助StringBuffer的初始化過程的優化技巧
  你可以通過StringBuffer的構造函數來設定它的初始化容量,這樣可以明顯地提升性能。這里提到的構造函數是StringBuffer(int length),length參數表示當前的StringBuffer能保持的字符數量。你也可以使用ensureCapacity(int minimumcapacity)方法在StringBuffer對象創建之后設置它的容量。首先我們看看StringBuffer的缺省行為,然后再找出一條更好的提升性能的途徑。
 
StringBuffer的缺省行為:
  StringBuffer在內部維護一個字符數組,當你使用缺省的構造函數來創建StringBuffer對象的時候,因為沒有設置初始化字符長度,StringBuffer的容量被初始化為16個字符,也就是說缺省容量就是16個字符。當StringBuffer達到最大容量的時候,它會將自身容量增加到當前的2倍再加2,也就是(2*舊值+2)。
  假如你使用缺省值,初始化之后接著往里面追加字符,在你追加到第16個字符的時候它會將容量增加到34(2*16+2),當追加到34個字符的時候就會將容量增加到70(2*34+2)。無論何事只要StringBuffer到達它的最大容量它就不得不創建一個新的字符數組然后重新將舊字符和新字符都拷貝一遍——這也太昂貴了點。所以總是給StringBuffer設置一個合理的初始化容量值是錯不了的,這樣會帶來立竿見影的性能增益。
  我利用兩個StringBuffer重新測試了上面的StringTest4.java代碼,一個未使用初始化容量值而另一個使用了。這次我追加了50000個’hello’對象沒有使用+操作符。區別是我使用StringBuffer(250000)的構造函數來初始化第二個 StringBuffer了。
 
輸出結果如下:
Time taken for String concatenation using StringBuffer with out setting size: 280 milli seconds
Time taken for String concatenation using StringBuffer with setting size: 0 milli seconds
StringBuffer初始化過程的調整的作用由此可見一斑。所以,使用一個合適的容量值來初始化StringBuffer永遠都是一個最佳的建議。
 
要害點
1. 無論何時只要可能的話使用字符串字面量來常見字符串而不是使用new要害字來創建字符串。
2. 無論何時當你要使用new要害字來創建很多內容重復的字符串的話,請使用String.intern()方法。
3. +操作符會為字符串連接提供最佳的性能——當字符串是在編譯期決定的時候。
4. 假如字符串在運行期決定,使用一個合適的初期容量值初始化的StringBuffer會為字符串連接提供最佳的性能。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品国产户外野外| 91精品在线看| 免费不卡在线观看av| 一区二区在线视频| 久久99精品久久久久久青青91| 久久久亚洲天堂| 国产美女精品视频| 亚洲欧美国产精品va在线观看| 97国产精品人人爽人人做| 日韩中文理论片| 欧美色视频日本高清在线观看| 日韩男女性生活视频| 日韩高清电影免费观看完整版| 成人黄色在线播放| 日韩国产中文字幕| 中文字幕亚洲一区二区三区| 国产91露脸中文字幕在线| 亚洲欧洲国产精品| 色综合久久88色综合天天看泰| 亚洲欧美日本伦理| 亚洲欧美综合另类中字| 亚洲国产精品va在线看黑人动漫| 久久综合伊人77777| 国内成人精品视频| 国产精品第一页在线| 丝袜亚洲欧美日韩综合| 日韩欧美亚洲成人| 亚洲男人的天堂在线播放| 欧美精品性视频| 亚洲人成网站色ww在线| 亚洲成人激情在线观看| 亚洲人a成www在线影院| 91在线高清视频| 91成人免费观看网站| 亚洲成人在线网| 国产精品欧美风情| 亚洲精品国产精品国自产观看浪潮| 亚洲欧美色图片| 久久亚洲春色中文字幕| 亚洲国产高潮在线观看| 亚洲电影免费观看高清完整版在线| 91精品久久久久久久久久另类| 一本色道久久88综合亚洲精品ⅰ| 在线播放国产一区中文字幕剧情欧美| 海角国产乱辈乱精品视频| 日韩精品视频中文在线观看| 国产狼人综合免费视频| 精品人伦一区二区三区蜜桃网站| 精品精品国产国产自在线| 中文字幕精品视频| 亚洲精品国偷自产在线99热| 国产日韩精品综合网站| 2019中文字幕在线| 丝袜亚洲欧美日韩综合| 精品亚洲男同gayvideo网站| 国产精品久久电影观看| 91中文精品字幕在线视频| 俺也去精品视频在线观看| 亚洲人成电影网站色xx| 日韩女优人人人人射在线视频| 亚洲人成在线观看| 亚洲free性xxxx护士hd| 亚洲视频一区二区三区| 国产精品www色诱视频| 久久视频免费观看| 精品久久久久久久久久国产| 精品亚洲aⅴ在线观看| 亚洲成人精品在线| 国产97在线播放| 97婷婷大伊香蕉精品视频| 欧美日韩国产二区| 国产精品久久久一区| 欧美一级大片在线免费观看| 国产精品一区=区| 国产91精品久久久久久久| 91精品国产91久久久久| www.国产精品一二区| 精品国产老师黑色丝袜高跟鞋| 欧美精品在线观看| 亚洲区中文字幕| 久久精品在线播放| 97久久久久久| 精品国产电影一区| 国产精品xxxxx| 久久久久久久久爱| 国产日韩精品一区二区| 久久国产精品视频| 亚洲高清久久久久久| 欧美午夜丰满在线18影院| 不卡av日日日| 综合国产在线观看| 亚洲第一精品夜夜躁人人躁| 2019最新中文字幕| 亚洲在线免费观看| 动漫精品一区二区| 91在线色戒在线| 欧美尺度大的性做爰视频| 亚洲中国色老太| 狠狠躁18三区二区一区| 欧美极品少妇xxxxⅹ裸体艺术| 国产精品美女av| 欧美限制级电影在线观看| 中文字幕欧美亚洲| 日韩电影第一页| 在线电影欧美日韩一区二区私密| 欧美性受xxxx黑人猛交| 97色在线观看免费视频| 国产日韩欧美视频在线| 国产一区二区三区四区福利| 日韩av在线免费观看| 亚洲乱亚洲乱妇无码| 91精品在线国产| 久久亚洲精品网站| 在线日韩av观看| 中文字幕在线视频日韩| 91精品国产高清久久久久久| 成人免费看黄网站| 91国产视频在线| 狠狠躁天天躁日日躁欧美| 激情成人在线视频| 中文字幕精品网| 欧美极品美女视频网站在线观看免费| 日韩在线观看免费全集电视剧网站| 九九精品在线播放| 国产精品久久一区| www国产亚洲精品久久网站| 亚洲aⅴ男人的天堂在线观看| 国产精品一区二区电影| 国产精品久久久久影院日本| 久久人人看视频| 亚洲成人三级在线| 欧美成人在线网站| 国产亚洲精品美女| 91av在线免费观看视频| 亚洲国内精品视频| 国产精品第一视频| 68精品久久久久久欧美| 久久夜色撩人精品| 久久久中文字幕| 午夜精品久久久久久久白皮肤| 日韩欧美一区二区三区久久| 欧美黑人性猛交| 欧美人交a欧美精品| 欧美xxxx14xxxxx性爽| 日韩av123| 亚洲精品中文字幕有码专区| 精品一区精品二区| 国产精品永久免费| 成人黄色免费网站在线观看| 亚洲一区第一页| 91精品国产高清自在线| 久久av中文字幕| 欧美激情视频网站| 日韩在线视频免费观看高清中文| 欧美在线中文字幕| 中文字幕在线亚洲| 国产精品美乳一区二区免费| 欧美激情免费看| 美女精品视频一区| 国产精品视频男人的天堂| 一区二区三区美女xx视频| 亚洲福利视频久久| 国产91精品久久久久| 日韩精品在线视频观看|