admin管理员组文章数量:1611561
今天,简单讲讲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 StringBuilder
extends AbstractStringBuilder
implements 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[]里填东西的过程。
public StringBuilder append(String str) {
super.append(str);
return this;
}
其中,super.append是调用AbstractStringBuilder 的append(String str)方法,如下:
public AbstractStringBuilder append(String str) {
if (str == null) str = "null";
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
StringBuilder的扩容和ArrayList有些类似,具体代码如下:
/**
* This method has the same contract as ensureCapacity, but is
* never synchronized.
*/
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (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) // overflow
throw 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的使用就讲完了。
就这么简单。
本文标签: androidStringBuilderCapacity
版权声明:本文标题:android StringBuilder的Capacity的使用 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dianzi/1728620089a1166241.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论