JavaString、StringBuilder、StringBuffer總結,stringbuilder

來源:互聯網
上載者:User

JavaString、StringBuilder、StringBuffer總結,stringbuilder

背景:

       最近項目中需要用到伺服器模板和字串拼接技術。伺服器模板技術很多,JSP、Velocity、JDynamiTe等很多。字串拼接技術在Java中更簡單,StringBuilder、StringBuffer和重載的字串“+”操作。但是實際開發中,發現自己平時對Java的字串拼接的細節處理真的很差。

 

基礎:

       字串操作主要問題在效率上,包括如下兩點:

       (1)拼接效率。

       (2)尋找、回溯效率。

       凡是瞭解Java的都知道下面3點,而且這肯定是Java面試時必考的。

       (1)StringBuilder是安全執行緒的;

       (2)StringBuffer是線程不安全的;

       (3)Java的String是final的,而且Java的String對象是放在字串常量池的。

 

       其實在這之前,我對這幾點也只是“知其然而不知其所以然”,因為懶惰的關係,這三個類的源碼也沒看過,今天終於有時間看了下,順便總結下。

 

繼承體系

       這個三個類的繼承體系如下:

 

       (1)他們都實現了CharSequence介面,而且都是可以被序列化、被比較大小的。

       (2)閱讀它們的源碼可以知道,他們在管理字串時,都使用的char數組。其實字串本身就是一種資料結構,和Stack、Queue一樣,只是String資料結構太常見了,才導致我們已經不把它當成一種資料結構了。

       (3)StringBuilder和StringBuffer有一個共同的抽象父類AbstractStringBuilder,凡是對StringBuilder的方法調用,在StringBuilder內部都是調用的super方法,StringBuffer也一樣,只不過StringBuffer在自己的方法上加上了synchronized關鍵字。

 

append方法

       我們對StringBuilder和StringBuffer調用最多的應該就是append方法了,append方法有很多重載方法,這些重載方法的實現思路都是一樣的,首先把傳入的參數轉換為char數組,然後把char數組和自己本身的數組進行合并,至於合并演算法就很簡單了(不過可以注意下合并後char數組的長度)。

       不同類型的參數轉換為char數組的方式略有不同,Object類型調用String的靜態方法valueOf,基本類型的除了char和boolean外,都是調用的他們類型本身的getChars靜態方法。char添加比其他類型略快,不用調用getChars方法,boolean則直接添加一個[‘t’,’r’,’u’,’e’]或者[‘f’,’a’,’l’,’s’,’e’]字元數組。

       所以從上面可以看出,調用append方法的時候如果可以直接append一個char或者char數組是最好的。

 

String

       接著說下String,我們都知道JVM本身是對String對象有過最佳化的,而且實現了對String的操作符(+)的重載。JVM把String對象都放在常量池中,每次new對象的時候,都先去檢查常量池存不存在一個相同的字串序列,如果存在序列相同的就返回這個對象,如果不存在則建立一個新的。

       有一個不負責任的笼統說法:JVM對String + 的重載其實是在編譯階段把+ 翻譯成了StringBuilder(JDK 1.4前是StringBuffer)。


比如:

String s = “a”;String m = s + “a” + “d”;

編譯後就是:

String s =”a”;String m = (new StringBuilder(s)).append(“a”).append(“d”).toString();


       所以,根據這個規律我們在for迴圈中使用+操作效率是比較低的。

       當然上面的情況是有特例的,畢竟Java編譯機制不會這麼簡單,比如當Java編譯器在編譯時間能確定字串的值時就不會遵循上面的編譯規則。

String s= “a”;String m = “s” + “x” + “e”;

       這個時候m的值可以被確定,因為沒有變數參與運算,就可以直接賦值為sxe字串對象。

 

總結:

       在構造StringBuilder的時候能確定序列長度,最好指定序列長度,這樣能減少append時的數組copy。

       在使用StringBuilder的時候如果可以盡量使用append字元的方式,如:append(‘a’)比append(“a”)要好,而且不會產生字串a的對象。但是也不要特意這樣,比如append(‘a’).append(‘b’).append(‘c’)替代append(“abc”),那就有點畫蛇添足了。

       其次,在append的參數中少用字串+操作,如果大量的使用字串+操作有的時候會失去使用StringBuilder的意義。比如

       append(“a”+s+”d”);

應該拆分為

       append(‘a’).append(s).append(‘d’);

       這樣在大量迴圈中,能幫我們提高效率。

       最後,關於字串的尋找和回溯操作,如果可以,我們可以直接使用索引的方式去截取字串也就是操作String類的API,這比在Java中使用Regex要好很多。




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.