摘要:不指定容量會顯著降低性能一般使用在方法內(nèi)部來完成類似功能,因為是線程不安全的,所以用完以后可以丟棄。主要用在全局變量中相同情況下使用相比使用僅能獲得左右的性能提升,但卻要冒多線程不安全的風(fēng)險。
String 作為最基礎(chǔ)的引用數(shù)據(jù)類型,日常的開發(fā)中被大量的使用?;诓豢勺兊奶匦?,一旦被過度地使用,堆內(nèi)存就會負(fù)荷不堪,甚至影響性能,為此,Java 設(shè)計者特意為 String 在方法區(qū)中開辟了字符串常量池,以減少 String 的實例創(chuàng)建,然而,在面對大數(shù)量的情況下,字符串常量池也未必能解決問題,因此,AbstractStringBuilder 應(yīng)運而生,就是為了解決 String頻繁創(chuàng)建而引發(fā)的內(nèi)存性能下降的問題。
帶著兩個問題,去看看String / StringBuffer / StringBuilder 的區(qū)別
String vs AbstractStringBuilder
StringBuffer vs StringBuilder
String / StringBuffer / StringBuilder 的使用策略
String vs AbstractStringBuilder
擴(kuò)容機(jī)制
String
不可變性:重新創(chuàng)建一個對象
String 底層代碼實現(xiàn):
String 類被 final 修飾,該類不能被繼承
value[] 屬性 被final 修飾 ,引用不能修改
public final class String implements java.io.Serializable, Comparable, CharSequence { /** The value is used for character storage. */ private final char value[]; // /** Cache the hash code for the string */ private int hash; // Default to 0``` //other codes
測試代碼:
String str = new String("a"); str = str + “b” ;
圖示:
AbstractStringBuilder
可變性
AbstractStringBuilder 底層代碼實現(xiàn):
value[] 相對于 String ,沒有被final修飾
append("String") 返回時對象本身,不會創(chuàng)建新的對象
abstract class AbstractStringBuilder implements Appendable, CharSequence { /** * The value is used for character storage. */ char[] value; /** * The count is the number of characters used. */ int count; // other codes public AbstractStringBuilder append(String str) { if (str == null) return appendNull(); int len = str.length(); ensureCapacityInternal(count + len); str.getChars(0, len, value, count); count += len; return this; } //other codes }
測試代碼:
StringBuffer sb = new StringBuffer("a"); sb.append("b");
圖示:
性能比較
public class StringBufferWithStringBuilder { public void testString() { long start = System.currentTimeMillis(); String str = null; for (int i = 0; i < 20000; i++) { str = str + i + ","; } System.out.println(System.currentTimeMillis() - start); } public void testStringBuffer() { long start = System.currentTimeMillis(); StringBuffer sbuf = new StringBuffer(); for (int i = 0; i < 20000; i++) { sbuf.append(i + ","); } System.out.println(System.currentTimeMillis() - start); } public void testStringBulider() { long start = System.currentTimeMillis(); StringBuilder builder = new StringBuilder(); for (int i = 0; i < 20000; i++) { builder.append(i + ","); } System.out.println(System.currentTimeMillis() - start); } @Test public void test(){ testString(); testStringBuffer(); testStringBulider(); } }
通過測試數(shù)據(jù)得知,在性能和效率上:StringBuilder>StringBuffer>String
原因在于:
String 每執(zhí)行一次 + 重載運算符,必須創(chuàng)建一個新的對象
StringBuilder 與 StringBuffer相比,少了同步鎖
StringBuffer vs StringBuilder
線程安全
StringBuffer 是線程安全的
StringBuilder 是線程不安全
底層實現(xiàn): StringBuffer 通過 synchronized 關(guān)鍵字的修飾,保證了資源不會被搶占,從而確保了線程安全
/** * @since 1.5 */ @Override public synchronized void trimToSize() { super.trimToSize(); } /** * @throws IndexOutOfBoundsException {@inheritDoc} * @see #length() */ @Override public synchronized void setLength(int newLength) { toStringCache = null; super.setLength(newLength); }String / StringBuffer / StringBuilder 的使用策略
基本原則:如果要操作少量的數(shù)據(jù),用String ;單線程操作大量數(shù)據(jù),用StringBuilder ;多線程操作大量數(shù)據(jù),用StringBuffer
不要使用String類的"+"來進(jìn)行頻繁的拼接,因為那樣的性能極差的,應(yīng)該使用StringBuffer或StringBuilder類,這在Java的優(yōu)化上是一條比較重要的原則
為了獲得更好的性能,在構(gòu)造 StringBuffer 或 StringBuilder 時應(yīng)盡可能指定它們的容量。當(dāng)然,如果你操作的字符串長度(length)不超過 16 個字符就不用了,當(dāng)不指定容量(capacity)時默認(rèn)構(gòu)造一個容量為16的對象。不指定容量會顯著降低性能
StringBuilder一般使用在方法內(nèi)部來完成類似"+"功能,因為是線程不安全的,所以用完以后可以丟棄。StringBuffer主要用在全局變量中
相同情況下使用 StringBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的性能提升,但卻要冒多線程不安全的風(fēng)險。而在現(xiàn)實的模塊化編程中,負(fù)責(zé)某一模塊的程序員不一定能清晰地判斷該模塊是否會放入多線程的環(huán)境中運行,因此:除非確定系統(tǒng)的瓶頸是在 StringBuffer 上,并且確定你的模塊不會運行在多線程模式下,才可以采用StringBuilder;否則還是用StringBuffer
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/67220.html
摘要:所以如果要進(jìn)行的操作是多線程的,那么就要使用,但是在單線程的情況下,還是建議使用速度比較快的??偨Y(jié)一下適用于少量的字符串操作的情況適用于單線程下在字符緩沖區(qū)進(jìn)行大量操作的情況適用多線程下在字符緩沖區(qū)進(jìn)行大量操作的情況 [TOC] 原文鏈接:[https://www.cnblogs.com/su-fe...]: 這三個類之間的區(qū)別主要是在兩個方面,即運行速度和線程安全這兩方面 1、首先說...
摘要:當(dāng)然大多數(shù)情況下就是我們是在單線程下進(jìn)行的操作,所以大多數(shù)情況下是建議用而不用的,就是速度的原因。 第三階段 JAVA常見對象的學(xué)習(xí) StringBuffer和StringBuilder類 (一) StringBuffer類的概述 (1) 基本概述 下文以StringBuffer為例 前面我們用字符串做拼接,比較耗時并且也耗內(nèi)存(每次都會構(gòu)造一個新的string對象),而這種拼接操作又...
摘要:這兩個操作符都是編譯器默認(rèn)引入了類,最后都調(diào)用方法返回對象,臨時對象被回收,因此效率極為低下 Java String類筆記 聲明 文章均為本人技術(shù)筆記,轉(zhuǎn)載請注明出處https://segmentfault.com/u/yzwall String的不可變性 String的不可變性 // String declaration public final class String ...
摘要:與類基本相同,都是可變字符換字符串序列,不同點是是線程安全的,是線程不安全的。和區(qū)別在大部分情況下是線程安全的可變字符序列。在程序中可將字符串緩沖區(qū)安全地用于多線程。 轉(zhuǎn)載自飄過的小牛 我們先要記住三者的特征: String 字符串常量 StringBuffer 字符串變量(線程安全) StringBuilder 字符串變量(非線程安全) 一、定義 showImg(/...
本文原創(chuàng)文章,轉(zhuǎn)載注明出處,博客地址 https://segmentfault.com/u/to... 第一時間看后續(xù)精彩文章。覺得好的話,順手分享到朋友圈吧,感謝支持。 筆者經(jīng)常忘記三者之間的區(qū)別,下面自己總結(jié)一番,畫一個表格來展示 Item +區(qū)別 多線程 性能 使用場景 優(yōu)化 String 不可變類,重新創(chuàng)建字符串 不安全 拼接時,性能差 操作少量數(shù)據(jù),字符串不變時 無 St...
閱讀 2917·2021-11-23 09:51
閱讀 1567·2021-11-15 11:36
閱讀 3026·2021-10-13 09:40
閱讀 1919·2021-09-28 09:35
閱讀 13108·2021-09-22 15:00
閱讀 1383·2019-08-29 13:56
閱讀 2937·2019-08-29 13:04
閱讀 2707·2019-08-28 18:06