【轉】Java:String、StringBuffer和StringBuilder的區別

1 String

String:字符串常量,字符串長度不可變。Java中String是immutable(不可變)的。

String類的包含如下定義:

?

[java]?view plaincopy
  1. /**?The?value?is?used?for?character?storage.?*/??
  2. private?final?char?value[];??
  3. ??
  4. /**?The?offset?is?the?first?index?of?the?storage?that?is?used.?*/??
  5. private?final?int?offset;??
  6. ??
  7. /**?The?count?is?the?number?of?characters?in?the?String.?*/??
  8. private?final?int?count;??

用于存放字符的數組被聲明為final的,因此只能賦值一次,不可再更改。

?

2 StringBuffer(JDK1.0)

StringBuffer:字符串變量(Synchronized,即線程安全)。如果要頻繁對字符串內容進行修改,出于效率考慮最好使用StringBuffer,如果想轉成String類型,可以調用StringBuffer的toString()方法。

Java.lang.StringBuffer線程安全的可變字符序列。在任意時間點上它都包含某種特定的字符序列,但通過某些方法調用可以改變該序列的長度和內容。可將字符串緩沖區安全地用于多個線程。

StringBuffer 上的主要操作是 append 和 insert 方法,可重載這些方法,以接受任意類型的數據。每個方法都能有效地將給定的數據轉換成字符串,然后將該字符串的字符追加或插入到字符串緩沖區中。append 方法始終將這些字符添加到緩沖區的末端;而 insert 方法則在指定的點添加字符。例如,如果 z 引用一個當前內容是“start”的字符串緩沖區對象,則此方法調用 z.append("le") 會使字符串緩沖區包含“startle”,而 z.insert(4, "le") 將更改字符串緩沖區,使之包含“starlet”。

3 StringBuilder(JDK5.0)

StringBuilder:字符串變量(非線程安全)。在內部,StringBuilder對象被當作是一個包含字符序列的變長數組。

java.lang.StringBuilder是一個可變的字符序列,是JDK5.0新增的。此類提供一個與 StringBuffer 兼容的 API,但不保證同步。該類被設計用作 StringBuffer 的一個簡易替換,用在字符串緩沖區被單個線程使用的時候(這種情況很普遍)。

其構造方法如下:

?

構造方法描述
StringBuilder()創建一個容量為16的StringBuilder對象(16個空元素)
StringBuilder(CharSequence cs)創建一個包含cs的StringBuilder對象,末尾附加16個空元素
StringBuilder(int initCapacity)創建一個容量為initCapacity的StringBuilder對象
StringBuilder(String s)創建一個包含s的StringBuilder對象,末尾附加16個空元素

?

在大部分情況下,StringBuilder > StringBuffer。這主要是由于前者不需要考慮線程安全。

4 三者區別

String 類型和StringBuffer的主要性能區別:String是不可變的對象, 因此在每次對String 類型進行改變的時候,都會生成一個新的 String 對象,然后將指針指向新的 String 對象,所以經常改變內容的字符串最好不要用 String ,因為每次生成對象都會對系統性能產生影響,特別當內存中無引用對象多了以后, JVM 的 GC 就會開始工作,性能就會降低。

使用?StringBuffer 類時,每次都會對 StringBuffer 對象本身進行操作,而不是生成新的對象并改變對象引用。所以多數情況下推薦使用 StringBuffer ,特別是字符串對象經常改變的情況下。

在某些特別情況下, String 對象的字符串拼接其實是被 Java Compiler 編譯成了 StringBuffer 對象的拼接,所以這些時候 String 對象的速度并不會比 StringBuffer 對象慢,例如:

?

[java]?view plaincopy
  1. String?s1?=?“This?is?only?a”?+?“?simple”?+?“?test”;??
  2. StringBuffer?Sb?=?new?StringBuilder(“This?is?only?a”).append(“?simple”).append(“?test”);??

?

生成 String s1對象的速度并不比 StringBuffer慢。其實在Java Compiler里,自動做了如下轉換:

?

Java Compiler直接把上述第一條語句編譯為:

?

[java]?view plaincopy
  1. String?s1?=?“This?is?only?a?simple?test”;??

?

所以速度很快。但要注意的是,如果拼接的字符串來自另外的String對象的話,Java Compiler就不會自動轉換了,速度也就沒那么快了,例如:

[java]?view plaincopy
  1. String?s2?=?“This?is?only?a”;??
  2. String?s3?=?“?simple”;??
  3. String?s4?=?“?test”;??
  4. String?s1?=?s2?+?s3?+?s4;??

這時候,Java Compiler會規規矩矩的按照原來的方式去做,String的concatenation(即+)操作利用了StringBuilder(或StringBuffer)的append方法實現,此時,對于上述情況,若s2,s3,s4采用String定義,拼接時需要額外創建一個StringBuffer(或StringBuilder),之后將StringBuffer轉換為String;若采用StringBuffer(或StringBuilder),則不需額外創建StringBuffer。

5 使用策略

(1)基本原則:如果要操作少量的數據,用String ;單線程操作大量數據,用StringBuilder ;多線程操作大量數據,用StringBuffer。

(2)不要使用String類的"+"來進行頻繁的拼接,因為那樣的性能極差的,應該使用StringBuffer或StringBuilder類,這在Java的優化上是一條比較重要的原則。例如:

?

[java]?view plaincopy
  1. String?result?=?"";??
  2. for?(String?s?:?hugeArray)?{??
  3. ????result?=?result?+?s;??
  4. }??
  5. ??
  6. //?使用StringBuilder??
  7. StringBuilder?sb?=?new?StringBuilder();??
  8. for?(String?s?:?hugeArray)?{??
  9. ????sb.append(s);??
  10. }??
  11. String?result?=?sb.toString();??

當出現上面的情況時,顯然我們要采用第二種方法,因為第一種方法,每次循環都會創建一個String result用于保存結果,除此之外二者基本相同(對于jdk1.5及之后版本)

?

(3)為了獲得更好的性能,在構造 StirngBuffer 或 StirngBuilder 時應盡可能指定它們的容量。當然,如果你操作的字符串長度(length)不超過 16 個字符就不用了,當不指定容量(capacity)時默認構造一個容量為16的對象。不指定容量會顯著降低性能。

(4)StringBuilder一般使用在方法內部來完成類似"+"功能,因為是線程不安全的,所以用完以后可以丟棄。StringBuffer主要用在全局變量中。

(5)相同情況下使用 StirngBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的性能提升,但卻要冒多線程不安全的風險。而在現實的模塊化編程中,負責某一模塊的程序員不一定能清晰地判斷該模塊是否會放入多線程的環境中運行,因此:除非確定系統的瓶頸是在 StringBuffer 上,并且確定你的模塊不會運行在多線程模式下,才可以采用StringBuilder;否則還是用StringBuffer。

參考資料:

http://docs.oracle.com/javase/tutorial/java/data/buffers.html

http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.4

Java API

轉載于:https://www.cnblogs.com/Code-Farmer/p/4051786.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/376557.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/376557.shtml
英文地址,請注明出處:http://en.pswp.cn/news/376557.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux中exit與_exit的區別

在exit,_exit的區別 - exit()與_exit()函數的區別(Linux系統中)2012-03-20 15:19:53 分類: LINUX 注:exit()就是退出,傳入的參數是程序退出時的狀態碼,0表示正常退出,其他表示非正常退出&…

光標閃爍問題的解決辦法

在調用Windows API函數SetCursor設置光標時,可能會碰到閃爍的問題:移動鼠標,光標在Class Cursor(即注冊窗口類時指定的Cursor)與預設Cursor之間閃爍。 在MSDN上有關SetCursor函數的備注中強調,如果Class Cursor非空,那…

視頻編解碼基礎

文章目錄前戲編解碼技術流程主流視頻編碼標準視頻傳輸面臨的問題視頻傳輸差錯控制視頻傳輸Qos質量保證參數人類視覺系統HVS 以及相應編碼措施正餐編碼層次與碼流結構PB幀編碼IBBP序列編碼結構圖像編碼結構條帶編碼結構宏塊編碼結構塊編碼結構預測技術碼率控制實例H264前戲 編解…

XShell 屏幕鎖定的恢復方法(Ctrl+Q)

操作XShell過程中很多時間大家會習慣性的按CtrlS進行保存. CtrlS在XShell的作用是屏幕鎖定,很多朋友會無法操作,會直接把窗口關閉。 解決方法: 快捷鍵 CtrlQ 即能完成解鎖!轉載于:https://www.cnblogs.com/liangle/p/3173475.html

adb端口被占用

程序不能執行,kill掉任務管理器里面adb服務,重新連接設備仍然有錯 查到可能是adb端口被占用 查看adb用的是哪個端口:C:\Users\wanglin>adb nodaemon server 查看誰占用了這個端口:C:\Users\wanglin>netstat -ano | findstr …

實時語音通訊丟包補償技術

文章目錄基于發送端丟包補償技術原理與媒體無關的前向差錯糾正媒體相關前向差錯糾正交織技術基于接受端丟包補償技術基于插入方法基于插值方法基于重構的方法應用建議非交互式交互式拓展閱讀參考丟包補償技術可以分為兩類:基于發送端補償、基于接受端補償 基于發送…

取得裝置可以顯示頁面的寬度

利用html中的div元素取得<div id"divGetWidth" width100%></div>Jquery:var width$(#divGetWidth).width(); //獲取元素寬度 Javascript:var objdocument.getElementById(divGetWidth);var width obj.offsetWidth轉載于:https://www.cnblogs.…

Xcode添加靜態庫以及編譯選項配置常見問題

本文轉載至 http://www.cnblogs.com/Quains/archive/2013/08/22/3276425.html 一,Xcode編譯出現Link錯誤,出現"duplicate symbols for architecture i386 clang"提示.問題:鏈接時,項目有重名文件.解決:根據錯誤提示,做如下檢查:1.Taraget->Build Settings->Li…

關于并發概念的一些筆記

目錄1、基于鎖的并發數據結構1、并發計數器2、懶惰計數器3、并發鏈表4、并發隊列5、并發散列表總結2、條件變量使用&#xff08;POSIX&#xff09;生產者/消費者 &#xff08;有界緩沖區問題&#xff09;覆蓋條件擴展3、信號量使用二值信號量&#xff08;鎖&#xff09;0值信號…

MYSQL常見出錯代碼 mysql error number

1016錯誤&#xff1a;文件無法打開&#xff0c;使用后臺修復或者使用phpmyadmin進行修復。1044錯誤&#xff1a;數據庫用戶權限不足&#xff0c;請聯系空間商解決1045錯誤&#xff1a;數據庫服務器/數據庫用戶名/數據庫名/數據庫密碼錯誤&#xff0c;請聯系空間商檢查帳戶。105…

建立apk定時自動打包系統第三篇——代碼自動更新、APP自動打包系統

我們的思路是每天下班后團隊各成員在指定的時間&#xff08;例如下午18:30&#xff09;之前把各自的代碼上傳到SVN&#xff0c;然后服務器在指定的時間&#xff08;例如下午18:30&#xff09;更新代碼、執行ant 打包命令、最后將apk包存放在指定目錄&#xff08;或者上傳指定ft…

對于線程并發模型與事件并發模型的思考

這里將以對話的形式進行&#xff1a; A&#xff1a; 普通的線程是可以被其他線程中斷掉的&#xff0c;而基于select、epoll的事件處理函數實際上是不可以被其他事件&#xff08;線程&#xff09;中斷的。 我這個理解對嗎&#xff1f; B&#xff1a; 圖片里的應該是對是否…

Cache 總結

這一文&#xff0c;讓我們分析一下&#xff0c;《淺談 Cache》 一文中的奇怪現象&#xff0c;事實上如今來看也并不奇怪了。在什么情況下 r1 和 r2 都為 0 呢&#xff1f;細致看代碼&#xff0c;你會發現&#xff0c;兩個線程分別被執行在不同的 CPU 核上&#xff0c;而且在線程…

c/c++常見類型轉換錯誤

文章目錄char轉int 高位符號擴展有符號int與無符號int比較關于一個bit的位域變量的取值范圍臨時變量溢出size_t死循環char轉int 高位符號擴展 int main() {char a 0x9A;int util;util (int)a;cout << a << endl;cout << util << endl;if (util >…

Javascript 裝載和執行

一兩個月前在淘寶內網里看到一個優化Javascript代碼的競賽&#xff0c;發現有不少的人對Javascript的執行和裝載的基礎并不懂&#xff0c;所以&#xff0c;從那天起我就想寫一篇文章&#xff0c;但一直耽擱了。 首先&#xff0c;我想說一下Javascript的裝載和執行。通常來說&am…

java sundry tips

1.關于Arrays 記得binarySearch方法返回的int 類型的數值的含義。 If the array contains multiple elements with the specified value, there is no guarantee which one will be found. 而且當查找數小于數組中任何一個數時返回-1 &#xff0c;當查找數大于數組中任何…

c++常見的10個類對象問題

文章目錄1、對象的淺復制2、構造函數中的操作符重載3、拷貝構造函數不能模板化4、析構函數未捕獲異常導致coredump5、構造函數拋出異常6、基類析構函數非虛導致內存泄漏7、刪除void*指針引發內存泄露8、成員函數尾部缺失const9、使用memset初始化class10、對象向下轉換失敗1、對…

Ubuntu 14.10 -- 異次元軟件世界

Ubuntu 14.10 中文桌面版/服務器正式版下載 - 華麗免費易于入門的 Linux 操作系統 [ 系統工具 - Linux // 2014-10-25 ]一說到 Linux&#xff0c;就不得不提目前最紅火的 Ubuntu 發行版了&#xff01;它擁有絢麗的界面&#xff0c;甚至跟以時尚為賣點的 Mac OSX 相比也有過之而…

maven 概念

這里maven倡導約定優于配置&#xff0c;maven的約定就是以下目錄結構src/main/java 下存放java類src/main/webapp 下存放頁面文件(需要手動創建)src/main/resources 下存放資源文件src/test/java 下存放單元測試代碼src/test/resources 下存放測試資源文件 Maven運行的生命周期…

System Design筆記:在線售票系統設計

文章目錄何為在線售票系統&#xff1f;系統目標和要求1、功能要求2、非功能性需求3、設計注意事項4、容量估算5、系統API1.SearchMovies2.ReserveSeats6、數據庫設計7、高級設計8、細節模塊設計9、流程服務器如何跟蹤所有尚未預訂的active預訂&#xff1f;服務器如何跟蹤所有等…