java中String、StringBuffer、StringBuilder的區別

來源:互聯網
上載者:User

標籤:stat   abstract   儲存   ring   for   資料   final   字元數組   用法   

 

Java裡面提供了String,StringBuffer和StringBuilder三個類來封裝字串

0. 不當用法
String result = "";  for (String s : hugeArray) {      result = result + s;  }  

不要使用String類的"+"來進行頻繁的拼接,因為那樣的效能極差的,應該使用StringBuffer或StringBuilder類,這在Java的最佳化上是一條比較重要的原則

1. String類封裝的字串是不可變的

字串是由若干個字元線性排列組成的,String類的關鍵源碼如下

public final class String    implements java.io.Serializable, Comparable<String>, CharSequence {    /** The value is used for character storage. */   private final char value[];//final類型char數組//省略其他代碼…………}

因為有“final”修飾符,所以可以String類封裝的字串是不可變的。那麼增刪改是怎麼實現的呢?下面是字串截取的關鍵源碼

public String substring(int beginIndex) {        if (beginIndex < 0) {            throw new StringIndexOutOfBoundsException(beginIndex);        }        int subLen = value.length - beginIndex;        if (subLen < 0) {            throw new StringIndexOutOfBoundsException(subLen);        }       //當對原來的字串進行截取的時候(beginIndex >0),返回的結果是建立的對象        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);    }

可以看到截取源碼是產生了一個新的String對象返回的。

所以,在對String類型的字串進行大量“插入”和“刪除”操作時會產生大量的臨時變數。

既然String類封裝的字串是不可變的,那麼是否應該有一個類來封裝可變數組。答案是有的,StringBuilder與StringBuffer封裝類都是可變的。

2. 如何做到封裝數組可變

StringBuilder與StringBuffer都繼承自AbstractStringBuilder抽象類別,在AbstractStringBuilder中也是使用字元數組儲存字串,其關鍵代碼如下

abstract class AbstractStringBuilder implements Appendable, CharSequence {    /**     * The value is used for character storage.     */    char[] value;//一個char類型的數組,非final類型,這一點與String類不同    /**     * This no-arg constructor is necessary for serialization of subclasses.     */    AbstractStringBuilder() {    }    /**     * Creates an AbstractStringBuilder of the specified capacity.     */    AbstractStringBuilder(int capacity) {        value = new char[capacity];//構建了長度為capacity大小的數組    }//其他代碼省略…………}

StringBuffer類實現代碼如下

public final class StringBuffer    extends AbstractStringBuilder    implements java.io.Serializable, CharSequence{   /**     * Constructs a string buffer with no characters in it and an     * initial capacity of 16 characters.     */    public StringBuffer() {        super(16);//建立一個預設大小為16的char型數組    }    /**     * Constructs a string buffer with no characters in it and     * the specified initial capacity.     *     * @param      capacity  the initial capacity.     * @exception  NegativeArraySizeException  if the {@code capacity}     *               argument is less than {@code 0}.     */    public StringBuffer(int capacity) {        super(capacity);//自訂建立大小為capacity的char型數組    }//省略其他代碼…………

可以看到StringBuffer建立字串對象預設的大小是16,當然也可以傳入數組大小。

下面列下StringBuffer的用法

public class Test{  public static void main(String args[]){    StringBuffer sBuffer = new StringBuffer("hello");    sBuffer.append(" ");    sBuffer.append("world");    System.out.println(sBuffer);   }}

輸出

hello world

下面看源碼分析下append函數,來看下如何做到長度可變

public AbstractStringBuilder append(String str) {        if (str == null)            return appendNull();        int len = str.length();       //調用下面的ensureCapacityInternal方法        ensureCapacityInternal(count + len);        str.getChars(0, len, value, count);        count += len;        return this;    }private void ensureCapacityInternal(int minimumCapacity) {        // overflow-conscious code        if (minimumCapacity - value.length > 0)           //調用下面的expandCapacity方法實現“擴容”特性            expandCapacity(minimumCapacity);    }   /**     * This implements the expansion semantics of ensureCapacity with no     * size check or synchronization.     */    void expandCapacity(int minimumCapacity) {       //“擴充”的數組長度是按“擴充”前數組長度的2倍再加上2 byte的規則來擴充        int newCapacity = value.length * 2 + 2;        if (newCapacity - minimumCapacity < 0)            newCapacity = minimumCapacity;        if (newCapacity < 0) {            if (minimumCapacity < 0) // overflow                throw new OutOfMemoryError();            newCapacity = Integer.MAX_VALUE;        }        //將value變數指向Arrays返回的新的char[]對象,從而達到“擴容”的特性        value = Arrays.copyOf(value, newCapacity);    }

可以看到空間擴充室友copyOf函數實現:

public static char[] copyOf(char[] original, int newLength) {        //建立長度為newLength的char數組,也就是“擴容”後的char 數組,並作為傳回值        char[] copy = new char[newLength];        System.arraycopy(original, 0, copy, 0,                         Math.min(original.length, newLength));        return copy;//返回“擴容”後的陣列變數    }
3. StringBuilder與StringBuffer 區別

AbstractStringBuilder是StringBuilder與StringBuffer的公用父類,定義了一些字串的基本操作,如expandCapacity、append、insert、indexOf等公用方法,StringBuilder和StringBuffer的方法實現基本上一致,不同的是StringBuffer類的方法前多了個synchronized關鍵字,即StringBuffer是安全執行緒的。

public synchronized StringBuffer reverse() {    super.reverse();    return this;}public int indexOf(String str) {    return indexOf(str, 0);        //存在 public synchronized int indexOf(String str, int fromIndex) 方法}

(1)append,insert,delete方法最根本上都是調用System.arraycopy()這個方法來達到目的

(2)substring(int, int)方法是通過重新new String(value, start, end - start)的方式來達到目的。因此,在執行substring操作時,StringBuilder和String基本上沒什麼區別。

4. 使用情境

如果是多線程環境下涉及到共用變數的插入和刪除操作,StringBuffer則是首選。如果是非多線程操作並且有大量的字串拼接,插入,刪除操作則StringBuilder是首選。畢竟String類是通過建立臨時變數來實現字串拼接的,耗記憶體還效率不高,怎麼說StringBuilder是通過JNI方式實現終極操作的。

5. 總結
  • String類型的字串對象是不可變的,一旦String對象建立後,包含在這個對象中的字元系列是不可以改變的,直到這個對象被銷毀。
  • StringBuilder和StringBuffer類型的字串是可變的,不同的是StringBuffer類型的是安全執行緒的,而StringBuilder不是安全執行緒的
  • 如果是多線程環境下涉及到共用變數的插入和刪除操作,StringBuffer則是首選。如果是非多線程操作並且有大量的字串拼接,插入,刪除操作則StringBuilder是首選。
  • 如果要操作少量的資料,用String;單線程操作大量資料,用StringBuilder;多線程操作大量資料,用StringBuffer。

java中String、StringBuffer、StringBuilder的區別

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.