android StringBuilder的Capacity的使用
今天,簡單講講android里如何使用StringBuilder的Capacity屬性。
這個其實也很簡單,之前我寫個關于list的Capacity屬性的博客,說到了list的size和Capacity是不一樣的。同樣,StringBuilder的字符串的長度Length屬性和分配的空間Capacity屬性也是不一樣的。
StringBuilder 類表示可變字符的字符串。
| 名稱 | 說明 |
| Capacity屬性 | 獲取或設置可包含在當前實例所分配的內存中的最大字符數 |
| Length屬性 | 獲取或設置當前 StringBuilder 對象的長度 |
?
StringBuilder 類Capacity屬性的默認值為16。
??????????? StringBuilder sb = new StringBuilder();
??????????? Console.WriteLine("Length屬性:" + sb.Length + "Capacity屬性:" + sb.Capacity);
??????????? Console.ReadLine();
?
?
當StringBuilder 對象的Length屬性值超過Capacity屬性的長度時,StringBuilder 對象內部會重新構造一個字符數組。Capacity屬性會變為以前的2倍。例如:Capacity屬性的默認值為16,當追加字符串的長度超過16時,Capacity屬性會擴充為32。
StringBuilder sb = new StringBuilder();
??????????? //追加長度為17的字符串
??????????? sb.Append("01234567890123456");
??????????? Console.WriteLine("Length屬性:" + sb.Length + " Capacity屬性:" + sb.Capacity);
??????? Console.ReadLine();
所以為了節省空間的浪費,最好在使用時指定初始化的大小。接下來看看android的源碼:
指定初始容量
先來看一下StringBuilder的源碼(JDK7)
public final class StringBuilderextends AbstractStringBuilderimplements java.io.Serializable, CharSequence {/** use serialVersionUID for interoperability */static final long serialVersionUID = 4383685877147921099L;/*** Constructs a string builder with no characters in it and an* initial capacity of 16 characters.*/public StringBuilder() {super(16);}/*** Constructs a string builder with no characters in it and an* initial capacity specified by the <code>capacity</code> argument.** @param capacity the initial capacity.* @throws NegativeArraySizeException if the <code>capacity</code>* argument is less than <code>0</code>.*/public StringBuilder(int capacity) {super(capacity);} }
StringBuilder的默認構造方法調用的是父類AbstractStringBuilder 中的AbstractStringBuilder(int capacity)構造方法,如下:
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;/*** 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];} }StringBuilder的內部有一個char[], 在調用StringBuilder的無參構造方法時其內部char[]的默認長度是16。當我們調用StringBuilder的append方法時,其實就是不斷的往char[]里填東西的過程。
其中,super.append是調用AbstractStringBuilder 的append(String str)方法,如下:
StringBuilder的擴容和ArrayList有些類似,具體代碼如下:
/*** This method has the same contract as ensureCapacity, but is* never synchronized.*/ private void ensureCapacityInternal(int minimumCapacity) {// overflow-conscious codeif (minimumCapacity - value.length > 0)expandCapacity(minimumCapacity); }/*** This implements the expansion semantics of ensureCapacity with no* size check or synchronization.*/ void expandCapacity(int minimumCapacity) {int newCapacity = value.length * 2 + 2;if (newCapacity - minimumCapacity < 0)newCapacity = minimumCapacity;if (newCapacity < 0) {if (minimumCapacity < 0) // overflowthrow new OutOfMemoryError();newCapacity = Integer.MAX_VALUE;}value = Arrays.copyOf(value, newCapacity); }
StringBuilder默認長度是16,然后,如果要append第17個字符,怎么辦?
答案是采用 Arrays.copyOf()成倍復制擴容!
擴容的性能代價是很嚴重的:一來有數組拷貝的成本,二來原來的char[]也白白浪費了要被GC掉。可以想見,一個129字符長度的字符串,經過了16,32,64, 128四次的復制和丟棄,合共申請了496字符的數組,在高性能場景下,這幾乎不能忍。
由此可見,合理設置一個初始值多重要。使用之前先仔細評估一下要保存的字符串最大長度。
簡單講講,就是StringBuilder在創建時內部分配了一個長度為16的字符數組,每次調用append時,會首先比較新的字符長度與內部數組的大小,如果大于就會進行擴容,擴容的方式是每次是原來容量的2倍。擴容后會將老的數據復制到新的字符數組里,然后將append(sb)里的數據考到新的字符數組里。所以這個是浪費了時間和內存的。所以在知道StringBuilde需要r的最大長度時,最好在使用前就指定初始化的容量Capacity。StringBuffer與StringBuilder都是繼承于AbstractStringBuilder,唯一的區別就是StringBuffer的函數上都有synchronized關鍵字。
android StringBuilder的Capacity的使用就講完了。
就這么簡單。
總結
以上是生活随笔為你收集整理的android StringBuilder的Capacity的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android handler.rem
- 下一篇: android 如何使用SAX解析XML