在java的String中有个一直被我们忽视了的方法intern方法:
它的官方解释是:
一个初始时为空的字符串池,它由类 String 私有地维护。 当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。
这里其实就是从堆中把栈的引用指向了常量池中,减少了重复的字符占空间!牺牲的速度不是一点半点的(几乎比equals方法慢了一倍多),但是intern对内存的优化也是很大的,试想所有重复的字符都被存入了常量池中,系统越复杂,体现出来的优化就越明显!
使用intern还是equals还是要结合场景,要速度就要牺牲空间,要空间就要牺牲速度!
对String的intern和equals的速度差异测试:
package test;
import java.util.Random;
/**
* @author mzy
*
*/
public class Test2 {
public static void main(String[] args) {
/*
String s = new String("str");
String s1 = "str";
System.out.println(s == s1);
s = s.intern();
// s1 = s1.intern();
System.out.println(s == s1);
*/
/*
String s = new String("1");
s = s.intern();
String s2 = "1";
System.out.println(s == s2);
String s3 = new String("1") + new String("1");
s3.intern();
String s4 = "11";
System.out.println(s3 == s4);
*/
/*
String s1 = "mzy";
String s2 = new String("mzy");
System.out.println(s1.intern() == s2.intern());
*/
/*
String s1 = "mzy";
System.out.println(s1.intern() == new Test2().getString().intern());
*/
String[] strs = new String[1000];
String s1 = "";
String s2 = "";
int tmp = 97;
long t = System.currentTimeMillis();
Random random = new Random(System.currentTimeMillis());
for(int i=0; i<10000; i++) {
for(int j=0; j<5; j++) {
s1 += (char)(tmp += random.nextInt(26));
s2 += (char)(tmp += random.nextInt(26));
}
// if(s1.equals(s2)) {} // 1366ms
if(s1.intern() == s2.intern()) {} // 2908ms
}
System.out.println((System.currentTimeMillis()-t)+"ms");
}
}