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