字符串的不可變性
定義一個(gè)字符串
String s = "abcd";
使用變量賦值
String s2 = s;
字符串連接
s = s.contact("ef");
可以看出飘蚯,String對象一旦被創(chuàng)建出來馍迄,就無法修改。如果需要一個(gè)可修改的字符串局骤,應(yīng)該使用StringBuffer或者StringBuilder攀圈,否則會(huì)有大量時(shí)間浪費(fèi)在垃圾回收上。
編譯器對“+”的優(yōu)化
- 對于String s = "a" + "b"峦甩,編譯后變成String s = "ab"赘来。
- 對于String s = "a" + 變量,編譯后用StringBuilder.append()方法替代凯傲,最后調(diào)用toString()方法犬辰。
字符串拼接的幾種方式
- 使用“+”拼接
String str = "str"; str += String.valueOf(i);
使用“+”拼接,實(shí)際上是用StringBuilder.append()冰单。
- String.concat()
String str = "str"; str = str.concat(String.valueOf(i));
String.contact實(shí)現(xiàn)的原理是幌缝,創(chuàng)建一個(gè)字符數(shù)組,長度是已有字符串和待拼接字符串的長度之和诫欠,再把兩個(gè)字符串的值復(fù)制到新的字符數(shù)組中涵卵,并使用這個(gè)字符數(shù)組創(chuàng)建一個(gè)新的String對象并返回。簡單地說就是new了一個(gè)新的String對象荒叼。
- StringBuilder.append()
StringBuilder builder = new StringBuilder("str"); builder.append(String.valueOf(i));
StringBuilder.append實(shí)現(xiàn)的原理是轿偎,StringBuilder內(nèi)部也有一個(gè)char數(shù)組,但不是final的甩挫,進(jìn)行append時(shí),會(huì)直接拷貝字符到內(nèi)部的字符數(shù)組中椿每,如果字符數(shù)組長度不夠伊者,會(huì)進(jìn)行擴(kuò)展。
- StringBuffer.append()
StringBuffer buffer = new StringBuffer("str"); buffer.append(String.valueOf(i));
StringBuffer.append和StringBuilder.append原理是一樣的间护,不同的是亦渗,StringBuffer的append方法是用synchronized修飾的,是線程安全的汁尺。
- String.join()
String str = "str"; str = String.join("", str, String.valueOf(i));
String.join內(nèi)部也是用StringBuilder來實(shí)現(xiàn)的法精。
字符串拼接性能大比拼
測試代碼都類似下面這段:
public void stringJoint1() {
long t1 = System.currentTimeMillis();
String str = "str";
for (int i = 0; i < 50000; i ++) {
str += String.valueOf(i);
}
long t2 = System.currentTimeMillis();
System.out.println("+ cost: " + (t2 - t1));
}
運(yùn)行結(jié)果:
String.concat cost: 1902
StringBuilder cost: 6
StringBuffer cost: 5
+ cost: 5202
String.join cost: 5298
多次運(yùn)行之后,可以觀察到大概的運(yùn)行效率是:
StringBuilder ≈ StringBuffer < String.contact < String.join ≈ "+"
- StringBuffer相對StringBuilder多了同步的操作,所以在單線程環(huán)境下運(yùn)行效率差不多搂蜓;
- String.contact每次都會(huì)創(chuàng)建新的字符串狼荞,所以會(huì)更慢一些;
- String.join和“+”每次都會(huì)創(chuàng)建StringBuilder對象所以更慢帮碰。
總結(jié)一下:
- 如果不在循環(huán)體中拼接字符串相味,直接使用+就可以。
- 如果在循環(huán)體中拼接字符串殉挽,非并發(fā)時(shí)使用StringBuilder丰涉,并發(fā)時(shí)使用StringBuffer。