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 http协议添加Auth