1. 程式人生 > 實用技巧 >Java之String/StringBuffer/StringBuilder

Java之String/StringBuffer/StringBuilder

目錄

三者關係

https://blog.csdn.net/jisuanjiguoba/article/details/82531868
https://www.runoob.com/w3cnote/java-different-of-string-stringbuffer-stringbuilder.html
https://www.zhihu.com/question/20101840

  • 快慢關係
    StringBuilder>StringBuffer>String
    為何String最慢呢?因為String是不可變的,所以要修改時(其實就是將String指向了一個新物件,內容是修改的字串值),涉及到建立和回收物件,所以耗時。具體解釋如下:
  • 執行緒安全與否
    String不可變,所以自然是執行緒安全
    StringBuffer是執行緒安全,因為很多方法都由synchronized關鍵詞來修飾
    StringBuilder不是執行緒安全的
  • 三者相互轉換
  1. String vs. StringBuffer (StringBuilder轉換類似)
public class StringAndStringBufferSwitch {
    public static void main(String[] args) {        
 
        //String -> StringBuffer
        //建立一個String物件
        String str = "Hi Java!";
        System.out.println(str); 
        //方式一:構造方法
        StringBuffer buffer = new StringBuffer(str);
        System.out.println(buffer); 
        //方式二:通過append方法
        StringBuffer buffer2 = new StringBuffer();
        buffer2.append(str);
        System.out.println(buffer2);

        //StringBuffer -> String
        //建立一個StringBuffer物件
        StringBuffer buffer3 = new StringBuffer();
        buffer3.append("Happy birthday Java!");
        System.out.println(buffer3); 
        //方式一:通過構造方法
        String str2 = new String(buffer3);  
        System.out.println(str2);         
        //方式二:通過toString方法
        String str3 = buffer3.toString();
        System.out.println(str3);
    }
}

String

https://github.com/CyC2018/CS-Notes
https://blog.csdn.net/fly_fly_fly_pig/article/details/82492491

  • 特性
    不可變,final修飾。在java8中,String內部使用char陣列;在java9中,使用byte陣列
    不可變的好處:適合作map的鍵值、天生支援多執行緒、比較安全(比如傳送網路地址時)、String pool的需要
  • 關於String的="xxx"和new String("xxx")區別,以及字串相等的判定,以及intern()函式的使用,見下面的程式碼解釋:
public class TestString {
	public static void main(String[] args) {
		//直接使用="xxx"構造,會自動將“xxx”放入String pool,因此s2構造時,直接指向s1當時構造的“abc”。因此兩者hashcode或==都一樣
		String s1 = "abc";
		String s2 = "abc";
		System.out.println(s1.equals(s2));
		System.out.println("s1.hashcode: "+s1.hashCode()+"; s2.hashcode: "+s2.hashCode());
		System.out.println(s1 == s2);
		//此時String pool中已有“abc”,因此雖然是使用new String("abc")新建一個物件,但是查詢到String pool已有,同樣也是指向相同的引用
		String s3 = new String("abc");
		System.out.println("s3.hashcode: "+s3.hashCode());
		//然而,若我們用new String新建兩個相同的字串但是之前未出現在String pool中,則兩者的引用不同
		String s4 = new String("xyz");
		String s5 = new String("xyz");
		System.out.println(s4.equals(s5)); //true,因為值相等
		System.out.println("s4.hashcode: "+s4.hashCode()+"; s5.hashcode: "+s5.hashCode());
		System.out.println(s4 == s5);  //不同,因為是兩個不同的物件,雖然指向的是同一個地址
		//所以要注意,hashcode相同,也不一定就是同一個物件~
		//使用intern()可手動將字串放入String pool,這樣的話==就為true
		String s6 = s4.intern();
		String s7 = s4.intern();
		System.out.println(s6.equals(s7));
		System.out.println("s6.hashcode: "+s6.hashCode()+"; s7.hashcode: "+s7.hashCode());
		System.out.println(s6 == s7);
		//若使用一個物件作為新new物件的建構函式的引數時,value和hash都相同,但是s7,s8還是不同的物件。。
		String s8 = new String(s7);
		System.out.println(s7.equals(s8));
		System.out.println("s7.hashcode: "+s7.hashCode()+"; s8.hashcode: "+s8.hashCode());
		System.out.println(s7 == s8);
	}
}
result:
true
s1.hashcode: 96354; s2.hashcode: 96354
true
s3.hashcode: 96354
true
s4.hashcode: 119193; s5.hashcode: 119193
false
true
s6.hashcode: 119193; s7.hashcode: 119193
true
true
s7.hashcode: 119193; s8.hashcode: 119193
false

注意:在 Java 7 之前,String Pool 被放在執行時常量池中,它屬於永久代。而在 Java 7,String Pool 被移到中。這是因為永久代的空間有限,在大量使用字串的場景下會導致 OutOfMemoryError 錯誤。

  • 關於new String("xxx")後的操作
    會生成兩個物件,一個是在String pool中生成指向“xxx”的字串物件,一個是new之後在堆上生成的字串物件
  • String類方法
    https://www.runoob.com/java/java-string.html

StringBuffer

https://www.runoob.com/java/java-stringbuffer.html

  1. 特殊方法:
public class TestStringBuffer {
	
	public static void main(String[] args) {
		StringBuffer s1 = new StringBuffer("abc");
		System.out.println(s1);
		s1.append("def");
		System.out.println(s1);
		s1.reverse();
		System.out.println(s1);
		s1.delete(1,2); //刪除下標為[1,2)的字元
		System.out.println(s1);
		s1.insert(1,1);  //(int offset, int i),將int型的i插入到字串offset位置,其他字元後移
		System.out.println(s1);
		s1.replace(1,4,"kkk");  //用“kkk”替換掉下標為[1,4)的字元
		System.out.println(s1);
	}
}
result:
abc
abcdef
fedcba
fdcba
f1dcba
fkkkba
  1. 與String同樣的方法見https://www.runoob.com/java/java-stringbuffer.html

StringBuilder

StringBuffer 與 StringBuilder 中的方法和功能完全是等價的
https://www.cnblogs.com/onetheway2018/p/11553168.html