StringBuffer
如果频繁进行字符串拼接,会有什么问题?
因为Java中字符串是不可变的,每一次拼接都会产生新的字符串,这样会占用大量的字符串常量池内存,造成浪费
例如:
String s = "Hello";
s += " World";
以上两行代码就在方法区内存中创建了3个字符串对象"Hello"," World"和"Hello World".
StringBuffer进行拼接
- String底层是一个不可修改的byte[]数组(final byte[] value),final修饰数组对象,所以字符串对象一旦创建不可变,但是引用是可以变的
- 如:String s = "xy"; s = "add"; 对象"xy"不可变,但是引用s可变 - 与之区别,StringBhffer底层实际上是一个"可修改"的数组 (byte[] value)
因为数组的长度不可变,所以StringBuffer进行字符串拼接的底层操作:
- 新建一个更大的数组用来存储
- System.arraycopy()后,释放原数组内存
- 引用指向新的数组
因此,想要提高StringBuffer的性能:
在创建StringBuffer的时候尽可能给定一个合适的初始化容量,以减少底层数组扩容的次数
示例:
public class StringBufferTest01 {
//使用拼接的方法,会浪费字符串常量池的内存
public static void main(String[] args) {
//无参构造:创建一个初始化容量为16个byte[]数组,字符串缓冲区对象
StringBuffer stringBuffer = new StringBuffer();
//使用方法append()进行字符串拼接
stringBuffer.append("abc");
stringBuffer.append(true);
stringBuffer.append(3.14);
System.out.println(stringBuffer);
//有参构造:可以指定初始化容量的构造方法
StringBuffer stringBuffer1 = new StringBuffer(50);
stringBuffer1.append("Hello World");
System.out.println(stringBuffer1);
}
}
StringBuilder
- StringBuffer中的方法都有:synchronized 关键字修饰,而StringBuilder中的方法都没有。
- synchronized 关键字:表示在多线程环境下运行是安全的
- StringBuffer是线程安全的,StringBuilder是非线程安全的,其他方面二者都是一样的
示例:
public class StringBuilderTest01 {
public static void main(String[] args) {
//使用StingBuilder也可以完成字符串的拼接
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("abc");
stringBuilder.append(true);
stringBuilder.append(3.14);
System.out.println(stringBuilder);
}
}