Java StringBuilder
Java 中的 StringBuilder 类是一种可变字符串类型,它提供了一种高效的字符串操作方式。与 String 类不可变不同,StringBuilder 可以修改字符串的内容而不会创建新的对象。在本文中,我们将从四个方面介绍 StringBuilder 类,包括其实现原理、构造方法、重要方法以及需要注意的事项。
注意,StringBuffer 和 StringBuilder 在使用方式上几乎是完全相同的,所以不再单独介绍 StringBuffe。它们的主要的区别如下:
StringBuffer | StringBuilder | |
---|---|---|
线程安全 | 是 | 否 |
效率 | 低(因为线程安全加锁) | 高 |
适用场景 | 多线程环境 | 单线程环境 |
初始容量 | 16 | 16 |
增长方式 | 翻倍+2 | 翻倍+2 |
API | 同步方法 | 非同步方法 |
JDK 版本 | JDK 1.0 | JDK 1.5 |
StringBuilder 实现原理
StringBuilder 的实现原理是基于可变字符数组的动态扩容机制。StringBuilder 类在创建对象时会默认创建一个字符长度为 16 个字符的数组,具体的结构如下图所示。
创建的代码:
StringBuilder sb = new StringBuilder();
sb.append("wdbyte.com");
sb.append("1");
对应的逻辑图:
在 append()
方法中,StringBuilder 类会将要添加的字符串插入到字符数组,从而实现字符串的拼接,且不需要创建新的对象。
当需要添加的字符串长度超过当前字符数组长度时,StringBuilder 会使用Arrays.copyOf()
方法将字符数组扩容为原来的两倍加二。这在源码中可以看到。
private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2; // 2 倍 + 2
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
可见,StringBuilder 内部就是维护了一个可以动态扩容的字符数组,在拼接字符时,如果数组尚有空间,就可以不用创建对象直接把字符放入到字符数组指定位置,以此来节省资源。
可能你已经发现 StringBuilder 的优势了,在进行大量字符串拼接时,StringBuilder 的效率要远高于 String 类型的字符串拼接。因为 String 类型的字符串拼接会涉及到多次创建新的字符串对象,而 StringBuilder 则可以通过动态扩容的方式避免这种性能问题。
StringBuilder 构造方法
StringBuilder 类有多个构造方法,其中最常用的是无参构造方法和带有初始值的构造方法。无参构造方法会创建一个空的 StringBuilder 对象,内部会创建一个默认长度为 16 的字符数组。而带有初始值的构造方法则会创建一个包含指定字符序列的 StringBuilder 对象,维护的字符数组长度为传入的字符串长度加上 16。
StringBuilder sb1 = new StringBuilder();
System.out.println(sb1.capacity()); // 容量:16
StringBuilder sb2 = new StringBuilder("wdbyte.com");
System.out.println(sb1.capacity()); // 容量:26
StringBuilder重要方法
StringBuilder 类提供了多个实用的方法,包括 append、insert、delete、replace 等。
方法名 | 功能解释 |
---|---|
StringBuilder() |
创建一个空的 StringBuilder 对象 |
StringBuilder(int capacity) |
创建一个具有指定初始容量的 StringBuilder 对象 |
append(String str) |
将指定字符串添加到此字符序列的末尾 |
insert(int offset, String str) |
将指定字符串插入此字符序列中的指定位置 |
replace(int start, int end, String str) |
用指定字符串替换此序列的子字符串 |
delete(int start, int end) |
移除此序列的子字符串中的字符 |
reverse() |
将此字符序列用其反转形式取代 |
append
append 方法用于将指定的字符串追加到当前 StringBuilder 对象的末尾。它有多个重载方法,可以接受不同类型的参数。
StringBuilder sb3 = new StringBuilder("www");
sb3.append(".wdbyte.com");
System.out.println(sb3.toString()); // www.wdbyte.com
insert
insert 方法用于将指定的字符或字符串插入到当前 StringBuilder 对象的指定位置。它也有多个重载方法,可以接受不同类型的参数。
StringBuilder sb4 = new StringBuilder("wdbyte");
sb4.insert(0,"www.");
System.out.println(sb4.toString()); // www.wdbyte
sb4.insert(10,".com");
System.out.println(sb4.toString()); // www.wdbyte.com
delete
delete 方法用于删除当前 StringBuilder 对象中指定位置的字符。它有两个重载方法,可以删除单个字符或一段字符。
StringBuilder sb5 = new StringBuilder("www.wdbyte.com");
sb5.delete(0,4);
System.out.println(sb5); // wdbyte.com
replace
replace 方法用于将当前 StringBuilder 对象中指定位置的字符替换为指定的字符或字符串。它也有多个重载方法,可以接受不同类型的参数。
StringBuilder sb6 = new StringBuilder("hello world!");
sb6.replace(6,11, "java"); // 结果为 "hello java!"
reverse
将此字符序列用其反转形式取代。
StringBuilder sb7 = new StringBuilder("hello world!");
sb7.reverse();
System.out.println(sb7); // 结果:!dlrow olleh
StringBuilder 注意事项
StringBuilder 对象的操作是非线程安全的,如果需要在多线程环境下使用字符串操作,建议使用 StringBuffer 类。此外,在创建 StringBuilder 对象时,如果预计字符串长度较长,可以通过构造方法传入初始容量,避免频繁扩容所带来的性能损失。
StringBuilder sb = new StringBuilder(100); // 初始容量为100 的 StringBuilder 对象
一如既往,文章中代码存放在 Github.com/niumoo/javaNotes.