StringBuilder
StringBuilder用来高效拼接字符串
我们知道字符串是不可变的,所以下面我们拼接字符串的时候都是创建新的字符串并让变量指向新的字符串。如下,原来的字符串”start”还在,我们是创建了新的字符串 “start!” 。
public static void main(String[] args) {
String s1 = "start";
String s2 = s1;
s1= s1 + "!";
System.out.println(s1); // start!
System.out.println(s2); // start
}
经常不需要操作原字符串,所以一般不会用变量s2指向原字符串,这种没有任何变量指向的字符串对象会由垃圾回收机制自动处理掉。
public static void main(String[] args) {
String s1 = "start";
s1= s1 + "!";
System.out.println(s1); // start!
}
每次拼接字符串都创建了新的字符串对象,这样不但浪费内存,还会影响垃圾回收机制的效率。为了能高效拼接字符串,Java标准库提供了StringBuilder,它是一个可变对象,可以预分配缓冲区,这样,往StringBuilder中新增字符时,不会创建新的字符串对象。
StringBuilder会自动扩容,比如new StringBuilder(50)
就是分配了50字节的空间,如果字符串大小超过50字节就自动扩大容量。new StringBuilder()
不指明分配空间大小,则默认分配16字节。
如下我们希望获得最终结果的字符串,使用StringBuilder就不会每次拼接的时候都去创建新的字符串对象,节约了系统开销并且也不需要垃圾回收机制去处理原来的原字符串对象,可以提升性能。
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
sb.append("num");
for (int i = 0; i < 1000; i++) {
sb.append(i);
}
String s = sb.toString();
System.out.println(s);
}
StringBuilder还可以进行链式操作
public static void main(String[] args) {
var sb = new StringBuilder(1024);
sb.append("Mr ")
.append("Bob")
.append("!")
.insert(0, "Hello, ");
System.out.println(sb.toString()); // Hello, Mr Bob!
}
如果我们查看StringBuilder的源码,可以发现,进行链式操作的关键是,定义的append()方法会返回this,这样,就可以不断调用自身的其他方法。
新版Java完全没有必要使用StringBuffer
StringBuffer是Java早期的一个StringBuilder的线程安全版本,它通过同步来保证多个线程操作StringBuffer也是安全的,但是同步会带来执行速度的下降。
StringBuilder和StringBuffer接口完全相同,现在完全没有必要使用StringBuffer。
他の者にできたか?ここまでやれたか?この先できるか?いいや、仆にしかできない!