文章目錄
StringTable
1.什麼是stringtable?
字符串池在JDK1.7之後存在於堆中的一塊區域,String s1 = "abc"
這樣聲明的字符串會放入字符串池中,String s1 = new String("abcd")
會在字符串池有一個"abcd"的字符串對象,堆中也有1個,2個不同。
-
字符串池可以避免重複創建字符串對象
String s1 = "a"; String s2 = "a"; boolean isEqual = (s1 == s2);//爲true,因爲都是字符串池中的一個對象
-
常量池中的字符串僅是符號,第一次用到時才變爲對象
-
它的結構爲hash表結構,相同的字符串只存在一份
2. 字符串拼接原理
2.1字符串變量拼接
(代碼中 s1 + s2
)的原理是 new StringBuilder(),再調用它的append方法,最後調用它的toString(),實際是new String
2.2 字符串常量拼接
(代碼中"a" + "b"
)的原理是編譯期優化,編譯器認爲是常量,拼接結果唯一,去字符串池中找
3. 字符串延遲加載
利用idea中的Memory驗證字符串的延遲加載,執行到的時候才加載,不是一次加載完(觀察字符串個數)
- Memory可以查看運行時每類對象的個數
4. intern()–將串池中還沒有的字符串對象放入串池
可以使用 intern 方法,主動將串池中還沒有的字符串對象放入串池
- 1.8 將這個字符串對象嘗試放入串池,如果有則並不會放入,如果沒有則放入串池, 會把串 池中的對象的引用返回
- 1.6 將這個字符串對象嘗試放入串池,如果有則並不會放入,如果沒有會把此對象複製一份, 放入串池, 會把串池中的對象返回
5. 串池中的對象也會被GC回收
6. stringtable 性能調優
相關虛擬機參數
-
-XX:+PrintStringTableStatistics
-
-XX:StringTableSize
6.1 調整虛擬機參數-XX:StringTableSize
stringtable的數據結構爲哈希表,如果程序裏字符串常量的個數非常多,可以適當修改虛擬機參數-XX:StringTableSize(桶的個數,最小爲1009)的大小:原理是增大桶的數量,減小衝突,提升效率
eg:逐行讀取一個包含每行都是一個單詞,共計48W個單詞的文本文件,讀取到一個字符串變量,並調用intern()方法加入到stringtable中,修改虛擬機參數StringTableSize分別爲不設置,1009,200000觀察讀取花費的總時間。結論:stringtablesize越小,耗時越多.
/**
* 演示串池大小對性能的影響
* -Xms500m -Xmx500m -XX:+PrintStringTableStatistics -XX:StringTableSize=1009
*/
public class Demo1_24 {
public static void main(String[] args) throws IOException {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("linux.words"), "utf-8"))) {
String line = null;
long start = System.nanoTime();
while (true) {
line = reader.readLine();
if (line == null) {
break;
}
line.intern();
}
System.out.println("cost:" + (System.nanoTime() - start) / 1000000);
}
}
}
6.2 考慮將字符串入池
前提是程序中存在大量(幾十萬,百萬個)字符串,且有很多重複的情況
以上弄懂,下面這些就能搞明白啦
String s1 = "a";
String s2 = "b";
String s3 = "a" + "b";
String s4 = s1 + s2;
String s5 = "ab";
String s6 = s4.intern();
// System.out.println(s3 == s4); //false
System.out.println(s3 == s5); //true
System.out.println(s3 == s6);
String x2 = new String("c") + new String("d");
String x1 = "cd";
x2.intern();
// 如果調換了【最後兩行代碼】的位置呢,如果是jdk1.6呢
System.out.println(x1 == x2);