天天看點

String,StringBuffer,StringBuilder詳解

1.String 字元串是不可變的,底層是一個final修飾的char類型的數組,如下圖:

String,StringBuffer,StringBuilder詳解

String對象在指派後,都會在字元串常量池中緩存起來,如果下次建立時,會首先判斷常量池中是否已經存在緩存對象,如果有,則直接傳回該引用給建立者。

字元串常量池:是java記憶體中的一片記憶體空間。如下圖所示:

String,StringBuffer,StringBuilder詳解

通常來說,建立字元串的方式有如下兩種:

String str = "Cat";

String str1 = new String("Dog");

根據以上資訊,對下面的語句進行判斷

(1) String str1="Cat";

String str2 = "Cat";

String str3 = new String("Cat");

判斷:str1== str2

str1==str3

經過驗證測試如下:

String,StringBuffer,StringBuilder詳解

分析上述原因:

String str2 = "Cat"; 建立時,會首先去字元串常量池中查找看有沒有"Cat"字元串,如果有,則傳回它的位址給str2,如果沒有,則再常量池中建立一個"Cat"字元串,并将位址傳回給str1

String str3 = new String("Cat"); 建立時,會首先去字元串常量池中查找有沒有"Cat"字元串,如果沒有,則在字元串常量池中建立一個字元串,再在堆記憶體中建立一個"Cat"字元串,然後将堆記憶體中對應的位址傳回給str3,

如下圖所示:

String,StringBuffer,StringBuilder詳解

(2).String str = new String("hello");

在記憶體中會建立幾個對象?

答案是一個或兩個,取決于字元串常量池中有沒有“hello”字元串,如果有,則隻需要在堆記憶體中建立一個,是以答案是一個,如果沒有,則需要在字元串常量池和堆記憶體中各建立一個,是以是兩個。

(3).字元串拼接

String str="you";

String str2 = str+"win";

底層原理圖:

String,StringBuffer,StringBuilder詳解

是以,這種拼接方式的執行效率是比較低的,盡量不使用。

2.StringBuilder 是線程不安全的,但是執行效率比較高

3.StringBuffer 是線程安全的,但是執行效率比較低

String字元串的常用優化:

(1).split() 方法,建議使用indexOf()和subString()方法進行拆分。

(2).字元串的累加方式:

(2.1) String str = "mat";

String str2 = str+"mat";

(2.2)StringBuffer sb = new StringBuffer();

sb.append(“Cat”);

(2.3)StringBuilder sb = new StringBuilder()

sb.append();

針對以上三種方式,舉例說明:拼接一萬次的字元串"s",列印執行時間,如下:

public static void main(String[] args) {
		
		String str ="";
		long start1 =System.currentTimeMillis();
		for(int i=0;i<10000;i++){
			str=str+"s";
		}
		long end1 =System.currentTimeMillis();
		System.out.println("普通拼接一萬次耗時:"+(end1-start1)+"ms");
		
		long start2 = System.currentTimeMillis();
		StringBuffer sb = new StringBuffer();
		for(int i=0;i<10000;i++){
			sb.append("s");
		}
		long end2 =System.currentTimeMillis();
		System.out.println("StringBuffer拼接一萬次耗時:"+(end2-start2)+"ms");
	
		long start3 = System.currentTimeMillis();
		StringBuilder strBuilder = new StringBuilder();
		for(int i=0;i<10000;i++){
			strBuilder.append("s");
		}
		long end3 =System.currentTimeMillis();
		System.out.println("StringBuilder拼接一萬次耗時:"+(end3-start3)+"ms");

	}           

執行結果:

String,StringBuffer,StringBuilder詳解

(3).基本資料類型轉換成String類型的優化方案

(3.1) Integer num = 0;

String str = num+"";

(3.2)String str = String.valueOf(num);

(3.3) String str = num.toString();

針對以上三種方式,執行十萬次,看看時間消耗情況

Integer num = 0;
		long start1 =System.currentTimeMillis();
		for(int i=0;i<100000;i++){
			String str = num+"";
		}
		long end1 =System.currentTimeMillis();
		System.out.println("普通轉換一萬次耗時:"+(end1-start1)+"ms");
		
		
		long start2 =System.currentTimeMillis();
		for(int i=0;i<100000;i++){
			String str = String.valueOf(num);
		}
		long end2 =System.currentTimeMillis();
		System.out.println("valueOf()方法轉換一萬次耗時:"+(end2-start2)+"ms");
		
		
		long start3 =System.currentTimeMillis();
		for(int i=0;i<100000;i++){
			String str = num.toString();
		}
		long end3 =System.currentTimeMillis();
		System.out.println("toString()方法轉換一萬次耗時:"+(end3-start3)+"ms");           

執行結果如下:

String,StringBuffer,StringBuilder詳解

String.valueOf()直接調用了底層的Integer.toString()方法,不過其中會先判空;+""由StringBuilder實作,先調用了append()方法,然後調用了toString()方法擷取字元串;num.toString()直接調用了Integer.toString()方法,是以效率是:num.toString()方法最快,其次是String.valueOf(num),最後是num+""的方式

繼續閱讀