StringTable详解

StringTable详解

文章目录

StringTable1.什么是stringtable?2. 字符串拼接原理2.1字符串变量拼接2.2 字符串常量拼接

3. 字符串延迟加载4. intern()--将串池中还没有的字符串对象放入串池5. 串池中的对象也会被GC回收6. stringtable 性能调优6.1 调整虚拟机参数-XX:StringTableSize6.2 考虑将字符串入池

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);

相关推荐