1.String 字元串是不可變的,底層是一個final修飾的char類型的數組,如下圖:
String對象在指派後,都會在字元串常量池中緩存起來,如果下次建立時,會首先判斷常量池中是否已經存在緩存對象,如果有,則直接傳回該引用給建立者。
字元串常量池:是java記憶體中的一片記憶體空間。如下圖所示:
通常來說,建立字元串的方式有如下兩種:
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 str2 = "Cat"; 建立時,會首先去字元串常量池中查找看有沒有"Cat"字元串,如果有,則傳回它的位址給str2,如果沒有,則再常量池中建立一個"Cat"字元串,并将位址傳回給str1
String str3 = new String("Cat"); 建立時,會首先去字元串常量池中查找有沒有"Cat"字元串,如果沒有,則在字元串常量池中建立一個字元串,再在堆記憶體中建立一個"Cat"字元串,然後将堆記憶體中對應的位址傳回給str3,
如下圖所示:
(2).String str = new String("hello");
在記憶體中會建立幾個對象?
答案是一個或兩個,取決于字元串常量池中有沒有“hello”字元串,如果有,則隻需要在堆記憶體中建立一個,是以答案是一個,如果沒有,則需要在字元串常量池和堆記憶體中各建立一個,是以是兩個。
(3).字元串拼接
String str="you";
String str2 = str+"win";
底層原理圖:
是以,這種拼接方式的執行效率是比較低的,盡量不使用。
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");
}
執行結果:
(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.valueOf()直接調用了底層的Integer.toString()方法,不過其中會先判空;+""由StringBuilder實作,先調用了append()方法,然後調用了toString()方法擷取字元串;num.toString()直接調用了Integer.toString()方法,是以效率是:num.toString()方法最快,其次是String.valueOf(num),最後是num+""的方式