StringTable詳解

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. 1.8 將這個字符串對象嘗試放入串池,如果有則並不會放入,如果沒有則放入串池, 會把串 池中的對象的引用返回
  2. 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);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章