文章目录
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);