StringBuffer与StringBuilder
StringBuffer与StringBuilder
CAMELLIA!!! note 目录
StringBuffer与StringBuilder
StringBuffer
和StringBuilder
都是 Java 中用于创建和操作可变字符串的类都继承同一父类AbstractStringBuilder
。- 底层是byte[]数组,并且这个byte[]数组没有被final修饰,所以当byte[]数组满了,可以创建一个更大的新数组来达到扩容,然后他可以重新指向这个新数组对象。
- 优化策略:可以预估字符串的大致长度,初始化时设置合适的容量可以减少扩展数组的次数,从而提高性能。
- 在 Java 中,StringBuffer 和 StringBuilder 的初始默认容量(即字符数组的初始大小)都是 16。这个默认容量是由它们的共同父类 AbstractStringBuilder 定义的。
- StringBuilder和StringBuffer每次扩容为原来的2倍再加上2。
一、主要区别
线程安全性:
StringBuffer
是线程安全的,它的方法被同步以确保线程安全。因此,它可以在多线程环境中安全地使用。StringBuilder
不是线程安全的,它的性能比StringBuffer
更好,但不适合在多线程环境中使用。
性能:
- 由于
StringBuffer
的同步机制,它的操作速度相对较慢。 StringBuilder
没有同步机制,因此在单线程环境中操作速度更快。
- 由于
同步:
StringBuffer
:同步的,适合多线程环境。StringBuilder
:非同步的,适合单线程环境。
二、StringBuilder和StringBuffer构造方法
2.1 StringBuilder 构造方法
默认构造方法:
- 创建一个容量为 16 的空
StringBuilder
。
1
StringBuilder sb = new StringBuilder();
- 创建一个容量为 16 的空
指定初始容量的构造方法:
- 创建一个指定初始容量的
StringBuilder
。
1
StringBuilder sb = new StringBuilder(int capacity);
这里
capacity
是字符数组的初始容量。如果未指定,默认为 16。- 创建一个指定初始容量的
从字符串构造:
- 使用现有的字符串来初始化
StringBuilder
。
1
StringBuilder sb = new StringBuilder(String str);
这将创建一个与给定字符串相同内容的
StringBuilder
。- 使用现有的字符串来初始化
2.2 StringBuffer 构造方法
默认构造方法:
- 创建一个容量为 16 的空
StringBuffer
。
1
StringBuffer sb = new StringBuffer();
- 创建一个容量为 16 的空
指定初始容量的构造方法:
- 创建一个指定初始容量的
StringBuffer
。
1
StringBuffer sb = new StringBuffer(int capacity);
这里
capacity
是字符数组的初始容量。如果未指定,默认为 16。- 创建一个指定初始容量的
从字符串构造:
- 使用现有的字符串来初始化
StringBuffer
。
1
StringBuffer sb = new StringBuffer(String str);
这将创建一个与给定字符串相同内容的
StringBuffer
。- 使用现有的字符串来初始化
三、StringBuilder和StringBuffer的常用方法
StringBuilder append(Type data)
append
方法可以接受不同类型的数据作为参数,并将这些数据附加到现有的字符串构建器对象中而不产生新的对象。
1 |
|
- StringBuilder delete(int start, int end)
StringBuilder
类中的 delete(int start, int end)
方法用于删除字符序列中的一部分。
该方法接受两个参数:start
和 end
,它们定义了要删除的子字符串的起始和结束位置。
删除操作包括从 start
(包含)到 end
(不包含)之间的所有字符。
1 |
|
StringBuilder deleteCharAt(int index)
StringBuilder
类中的 deleteCharAt(int index)
方法用于删除指定索引位置的字符。
这个方法会移除 StringBuilder
对象中指定位置的字符,使得字符序列在该位置的字符被移除,并且之后的字符会向前移动。
1 |
|
StringBuilder insert(int offset,String str)
StringBuilder
类中的insert(int offset, String str)
方法用于在StringBuilder
对象的指定位置插入一个字符串。offset
参数确定了插入点的位置,str
是要插入的字符串。插入操作会将指定位置及其后的字符向后移动,给新的字符串腾出空间。
1 |
|
StringBuilder replace(int start,int end,String str)
StringBuilder
类中的replace(int start, int end, String str)
方法用于替换StringBuilder
对象中指定位置的字符序列。
该方法会将从start
到end
(不包括end)的字符替换为新提供的字符串 str
。
1 |
|
StringBuilder reverse()
StringBuilder
类中的reverse()
方法用于将字符串反转。它会改变StringBuilder
对象中的字符顺序,使得字符串中的字符按相反的顺序排列。
1 |
|
void setCharAt(int index,char ch)
在 Java 的StringBuilder
类中,setCharAt(int index, char ch)
方法用于将指定索引位置的字符替换为新的字符。
这个方法是对内部字符数组的直接操作,因此它可以在StringBuilder
对象的原始数据上进行修改,而不需要创建新的字符串对象。
1 |
|
void setLength(int newLength)
在 Java 的 StringBuilder
类中,setLength(int newLength)
方法用于设置字符串的长度。
这个方法可以用来增加或减少 StringBuilder
对象中字符的数量。当你使用 setLength
方法时,它会调整 StringBuilder
中实际存储的字符数组的大小,以符合指定的长度。
如果新长度小于当前长度,超出的部分将被截断;如果新长度大于当前长度,原字符串的末尾会填充空格字符(如果没有指定其他字符填充的话)。
1 |
|
注:
- StringBuffer和StringBuilder方法基本相同,除非在涉及多线程的问题上。
- 在多线程部分在具体学习StringBuffer
- 还有一些方法和String基本相同。
四、性能分析(String、StringBuilder)
4.1 String
不可变性:
String
对象在创建后是不可变的。这意味着每当你对一个String
对象进行拼接或修改操作时,实际上会创建一个新的String
对象。这种特性导致了以下几个性能影响:- 内存使用:每次拼接都会生成新的
String
对象,这会导致大量的内存分配和垃圾回收。 - 性能:频繁的字符串拼接操作会导致性能下降,因为每次拼接都会产生新的字符串实例,并且每次操作后都需要进行垃圾回收。
- 内存使用:每次拼接都会生成新的
适用场景:适用于较少修改的字符串,或不需要频繁进行字符串拼接的场景。
4.2 StringBuilder
可变性:
StringBuilder
是可变的,这意味着你可以在同一个对象上多次修改字符串内容,而不需要创建新的对象。这有以下几个优势:- 内存使用:由于避免了不必要的对象创建,
StringBuilder
在进行多次拼接时更加节省内存。 - 性能:
StringBuilder
在进行字符串拼接时通常比String
更高效,因为它直接在内部的字符数组上进行操作,而不是生成新的字符串对象。
- 内存使用:由于避免了不必要的对象创建,
适用场景:适用于频繁进行字符串拼接或修改的场景。
性能对比
- 内存开销:
StringBuilder
由于不需要为每次拼接操作创建新对象,因此在频繁拼接的情况下,相较于String
更加节省内存。 - 性能:在进行大量字符串拼接时,
StringBuilder
显示出比String
更高的性能。因为它通过内部的字符数组直接操作,避免了每次操作后的对象创建和垃圾回收。 - 线程安全性:
String
是线程安全的,因为它的不可变性保证了多个线程访问时不会发生状态变化。而StringBuilder
由于是可变的,在多线程环境中使用时需要额外的同步措施。
4.3 代码测试
1 |
|
1 |
|
相差太多,根本不是一个量级的。推荐频繁拼串使用StringBuilder。