Java StringBuilder和StringBuffer的用法及区别(附带实例)
java.lang.StringBuffer 和 java.lang.StringBuilder 都是用于处理字符串的辅助类,二者提供的方法几乎一致。它们底层都是用一个长度为 16 的数组对象来存储字符串值,代码如下:
若实例化时传递了参数,则会根据当前传递参数对象的长度值来决定字符串缓存区大小,即“实际参数对象长度+16”。这预留的 16 个字符的空间用来对字符串进行修改,如字符串拼接等。
当你调用 append() 或其他字符串操作方法时,StringBuffer 先检查数组容量是否能够装下新字符串,若装不下,则会对数组进行扩容,代码如下:
StringBuffer 与 StringBuilder 常用方法,如下表所示:
【实例】一个字符串为 hello,另一个字符串为 world,将两个字符串连接到一起,代码如下:
值得注意的是,StringBuffer 几乎所有的方法都使用关键字 synchronized 声明,这意味着你创建的 StringBuffer 对象对多个线程可见,即这种方法能够保证同一时间点最多只有一个线程调用该方法,用以保证并发编程下的安全。这种处理方式,在保证字符串操作正常的情况下兼顾安全性,牺牲了性能。
而 StringBuilder 没有实现线程同步,虽然不能保证线程安全,但效率比 StringBuffer 高。
如果在实际开发过程中定义的字符串不涉及修改,那么建议使用 String;如果字符串需要更改,不考虑线程安全,希望系统有更好的效率,那么建议使用 StringBuilder;当需要考虑线程安全时,不管怎样,都应该使用 StringBuffer。
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence{ public StringBuffer() { super(16); } public StringBuffer(String str) { super(str.length() + 16); append(str); } ...... }无参数实例化一个 StringBuffer 或 StringBuilder 对象的过程,就是创建一个长度为 16 字符的字符串缓存区。
若实例化时传递了参数,则会根据当前传递参数对象的长度值来决定字符串缓存区大小,即“实际参数对象长度+16”。这预留的 16 个字符的空间用来对字符串进行修改,如字符串拼接等。
当你调用 append() 或其他字符串操作方法时,StringBuffer 先检查数组容量是否能够装下新字符串,若装不下,则会对数组进行扩容,代码如下:
abstract class AbstractStringBuilder { ..... private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code if (minimumCapacity - value.length > 0) { value = Arrays.copyOf(value, newCapacity(minimumCapacity)); } } private int newCapacity(int minCapacity) { // overflow-conscious code int newCapacity = (value.length << 1) + 2; if (newCapacity - minCapacity < 0) { newCapacity = minCapacity; } return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0) ? hugeCapacity(minCapacity) : newCapacity; } }扩容的逻辑是创建一个新的 char 数组,将现有容量加一倍再加 2;若还是不够用,则其容量将等于所需容量大小。扩展完成后,将原始数组的内容复制到新数组中,最后将指针指向新的 char 数组。
StringBuffer和StringBuilder常用方法
StringBuffer 和 StringBuilder 类提供了很多操作字符串的方法,二者提供的方法几乎一样。对每种方法的详细描述,请参考 Java API 在线文档。StringBuffer 与 StringBuilder 常用方法,如下表所示:
方法 | 作用 |
---|---|
StringBuffer append(CharSequence s) | 拼接字符串 |
StringBuffer delete(int start, int end) | 删除指定范围内的内容 |
StringBuffer replace(int start, int end, String str) | 替换指定范围内的字符串 |
String substring(int start) | 返回从指定位置截取的字符串 |
StringBuffer insert(int index, char[] str, int offset, int len) | 插入字符串到指定位置 |
【实例】一个字符串为 hello,另一个字符串为 world,将两个字符串连接到一起,代码如下:
public class StringBufferBuilderDemo { public static void main(String[] args) { String str = "hello"; String str1 = "world"; StringBuffer sb = new StringBuffer(str); sb.append(str1); System.out.println(sb); } }程序运行结果为:
helloworld
上述代码显示,将 String 类型可以直接转换为 StringBuffer 类型,使用 StringBuffer 对象的 append() 方法进行拼接。StringBuilder和StringBuffer的区别
StringBuilder 和 StringBuffer 两个类提供的字符串操作几乎完全相同。值得注意的是,StringBuffer 几乎所有的方法都使用关键字 synchronized 声明,这意味着你创建的 StringBuffer 对象对多个线程可见,即这种方法能够保证同一时间点最多只有一个线程调用该方法,用以保证并发编程下的安全。这种处理方式,在保证字符串操作正常的情况下兼顾安全性,牺牲了性能。
而 StringBuilder 没有实现线程同步,虽然不能保证线程安全,但效率比 StringBuffer 高。
如果在实际开发过程中定义的字符串不涉及修改,那么建议使用 String;如果字符串需要更改,不考虑线程安全,希望系统有更好的效率,那么建议使用 StringBuilder;当需要考虑线程安全时,不管怎样,都应该使用 StringBuffer。