1.1 基本概念
- String描述的字符串是个常量,不可改变,会单独申请一块内存空间。在java代码中描述大量类似的字符串时,可能会造成内存空间的浪费
- 为了解决上述问题,使用可改变的字符串即可:
- Stringbuffer类 :JDK1.0开始存在,属于线程安全,所以效率低下
- StringBuilder类 :JDK1.5开始存在,属于非线程安全,所以效率较高
- 一般开发用StringBuilder
简单举例解释一下 ,线程安全和 非线程安全:
大妈买菜为例!一大堆大妈早上,就围在超市门口等开门,抢折扣的鸡蛋之类的食物。
-
线程安全:
大妈们,必须按照超市规定,排队,一个一个买。等结算完金额之后,下一个大妈才能开始购物。要20分钟,才能卖完
- 对于大妈来说:安全的
- 对于超市来说:卖东西的效率是低下的
-
非线程安全:
大妈们为了抢菜,又挤,又抢,还有人骂了起来,三下五除二,不到2分钟,菜就卖完了。
- 对于大妈来说:不安全的,可能会发生意外
- 对于超市来说:东西卖的贼快,效率高
1.2 StringBuilder常用的构造方法
方法声明 | 功能介绍 |
---|---|
StringBuilder() | 无参构造来构建对象,初始容量为16 |
StringBuilder( int capacity ) | 根据参数指定的容量,来构造对象 |
StringBuilder( String str ) | 根据字符串,来指定构造对象,容量大小为:16 + 字符串长度 |
1.3 StringBuilder常用成员方法
方法声明 | 功能介绍 |
---|---|
int capacity() | 返回方法调用对象的容量大小(虚拟大小) |
int length() | 返回字符串中的字符个数(实际大小) |
StringBuilder insert( int offset, String str) | 指定索引插入字符,返回引用(调用该方法) |
StringBuilder append( String str ) | 在字符串末尾追加字符串,返回引用 |
StringBuilder deleteCharAt( int index ) | 删除指定索引的字符,返回引用 |
StringBuilder delete( int start, int end ) | 从 start索引 开始删除字符,到 end索引-1 处,停止删除 |
StringBuilder replace( int start, int end, String str ) | 从 start索引 开始,到end索引-1 处的字符串,全部用 str替换掉 |
StringBuilder reverse() | 字符串翻转 |
1.4 StringBuilder的扩容算法的源码解析
举例探讨 StringBuilder的自动扩容机制:
StringBuilder sb = new StringBuilder("01234567");
String str = "qwertyuiop"
sb.append(str);
-
看append方法的源码:
@Override public StringBuilder append(String str) { // super,调用了父类的append方法 super.append(str); // 返回this,即返回当前调用该方法的对象 return this; }
-
(append源码内) 进入父类的append方法,查看源码
public AbstractStringBuilder append(String str) {
// 判断str是否为空
if (str == null)
return appendNull();
// 获取当前str的长度
int len = str.length();
// ensureCapacityInternal方法,确保容量足够的方法
// 参数count:即sb引用对象的长度,count= sb.length()
ensureCapacityInternal(count + len);
/* ______________ 进入ensureCapacityInternal方法 ____________*/
// minimumCapacity = 扩容前的长度 + 追加字符串的长度
private void ensureCapacityInternal(int minimumCapacity) {
// char[] value (Stringbuilder本质上就是一个字符数组)
// value.length:指Stringbuilder扩容前的容量
// 这个if判断,是用来判断是否扩容,true,则扩容
if (minimumCapacity - value.length > 0) {
// Arrays.copyOf: 数组的拷贝,将数组的内容拷贝到一个新的数组中
// 将 value,即扩容前的数组拷贝到, newCapacity(minimumCapacity)返回的数组中
// newCapacity(minimumCapacity)返回的是一个,扩容前的容量*2+2的一个容量大小的数组
value = Arrays.copyOf(
value,
newCapacity(minimumCapacity));
}
}
总结:
- StringBuilder的自动扩容机制为,扩容前的容量 * 2+ 2 = 扩容后的数组容量
- 要特别注意,容量 != 长度, 容量 = 数组能够拥有的最大长度
-
还有就是,如果一次性追加字符串的长度,超过了自动扩容后的容量。那么,会直接让追加后字符串的容量最为扩容后数组的容量
-
StringBuilder、StringBuffer作为参数时,会改变本身的值。而String就不会
1.5 常见笔试考点
考点1:StringBuilder类的对象本身会被修改,为什么成员方法还要返回自身对象呢?
为了连续调用,即链式编程
sb.reverse().append("1").insert(0, "X").delete(0, 3);
考点2:实现 StringBuilder 和 String 之间的相互转换
-
StringBuilder 转 String
String str = sb.toString();
-
String 转 StringBuilder
// 构造方法即可 StringBuilder s =new StringBuilder(str);
考点3:String,StringBuilder,StringBuffer三者之间效率比较
效率:StringBuilder > StringBuffer > String