在java的String中有个一直被我们忽视了的方法intern方法:
它的官方解释是:
一个初始时为空的字符串池,它由类 String 私有地维护。 当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。
这里其实就是从堆中把栈的引用指向了常量池中,减少了重复的字符占空间!牺牲的速度不是一点半点的(几乎比equals方法慢了一倍多),但是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"); } }