1、equals 比较内容 举例: String s1 = String s2 = String s3 = new String( s1 = s2; / true 地址相同 s1 = s3; / false 地址不同 s1.equals(s2); / true 内容相同 s1.equals(s3);intern() 方法 查找内容相同(equals()的字符串 / hello不存在,jvm创建新对象 (1) String s2 = new String( / 创举新对象 (2),这时heap中存在两个内容为hello的对象 / false / 地址不同 / true / 内容相同 s2 = s2.
2、intern(); / true / 找到对象(1) 并赋予s2 / true ! / 注意:此时s1,s2同指向(1)效率:String 与 StringBuffer 情景1: (1) String result = + world (2) StringBuffer result = new String().append().append( (1) 的效率好于 (2),不要奇怪,这是因为JVM会做如下处理 编译前 String result = 编译后 String result = hello world 情景2: (1) public String getString(String s
3、1, String s2) return s1 + s2; (2) public String getString(String s1, String s2) return new StringBuffer().append(s1).append(s2); (1) 的效率与 (2) 一样,这是因为JVM会做如下处理 编译前 return s1 + s2; 编译后 return new StringBuffer().append(s1).append(s2); 情景3: (1) String s = s1 s += s2s3 (2) StringBuffer s = new StringBuff
4、er().append( (2) 的效率好于(1),因为String是不可变对象,每次+=操作都会造成构造新的String对象 情景4: (1) StringBuffer s = new StringBuffer(); for (int i = 0; i 50000; i +) s.append( (2) StringBuffer s = new StringBuffer(250000); (2) 的效率好于 (1),因为StringBuffer内部实现是char数组,默认初始化长度为16,每当字符串长度大于char 数组长度的时候,JVM会构造更大的新数组,并将原先的数组内容复制到新数组,(
5、2)避免了复制数组的开销关键点 1). 简单的认为 .append() 效率好于 + 是错误的! 2). 不要使用 new 创建 String 3). 注意 .intern() 的使用 4). 在编译期能够确定字符串值的情况下,使用效率最高 5). 避免使用 来构造字符串 6). 在声明StringBuffer对象的时候,指定合适的capacity,不要使用默认值(18) 7). 注意以下二者的区别不一样 - String s = abString和StringBuffer之概览创建字符串的较佳途径滞留字符串带来的优化连接字符串时的优化技巧借助StringBuffer的初始化过程的优化技巧关键
6、点非可变对象一旦创建之后就不能再被改变,可变对象则可以在创建之后被改变。String对象是非可变对象,StringBuffer对象则是可变对象。为获得更佳的性能你需要根据实际情况小心谨慎地选择到底使用这两者中的某一个。下面的话题会作详细的阐述。(注意:这个章节假设读者已经具备Java的String和StringBuffer的相关基础知识。)创建字符串的较佳途径你可以按照以下方式创建字符串对象:1. String s1 = 2. String s3 = new String( String s4 = new String(上面哪种方式会带来更好的性能呢?下面的代码片断用来测量二者之间的区别。St
7、ringTest1.javapackage com.performance.string;/* This class shows the time taken for creation of * String literals and String objects.*/public class StringTest1 public static void main(String args) / create String literals long startTime = System.currentTimeMillis(); for(int i=0;i50000;i+) long endTi
8、me = System.currentTimeMillis(); System.out.println(Time taken for creation of String literals : + (endTime - startTime) + milli seconds ); / create String objects using new keyword long startTime1 = System.currentTimeMillis(); long endTime1 = System.currentTimeMillis();Time taken for creation of St
9、ring objects : + (endTime1 - startTime1)+这段代码的输出: 0 milli seconds 170 milli secondsJVM是怎样处理字符串的呢?Java虚拟机会维护一个内部的滞留字符串对象的列表(唯一字符串的池)来避免在堆内存中产生重复的String对象。当JVM从class文件里加载字符串字面量并执行的时候,它会先检查一下当前的字符串是否已经存在于滞留字符串列表,如果已经存在,那就不会再创建一个新的String对象而是将引用指向已经存在的String对象,JVM会在内部为字符串字面量作这种检查,但并不会为通过new关键字创建的String对象
10、作这种检查。当然你可以明确地使用String.intern()方法强制JVM为通过new关键字创建的String对象作这样的检查。这样可以强制JVM检查内部列表而使用已有的String对象。所以结论是,JVM会内在地为字符串字面量维护一些唯一的String对象,程序员不需要为字符串字面量而发愁,但是可能会被一些通过new关键字创建的String对象而困扰,不过他们可以使用intern()方法来避免在堆内存上创建重复的String对象来改善Java的运行性能。下一小节会向大家展示更多的信息。下图展示了未使用intern()方法来创建字符串的情况。你可以自己使用=操作符和String.equals
11、()方法来编码测试上面提到的区别。=操作符会返回true如果一些引用指向一个相同的对象但不会判断String对象的内容是否相同;String.equals()方法会返回true如果被操作的String对象的内容相同。对于上面的代码会有s1=s2,因为s1和s2两个引用指向同一个对象,对于上面的代码,s3.equals(s4)会返回true因为两个对象的内容都一样为”hello”。你可以从上图看出这种机制。在这里有三个独立的包含了相同的内容(”hello”)的对象,实际上我们不需要这么三个独立的对象因为要运行它们的话既浪费时间又浪费内存。那么怎样才能确保String对象不会重复呢?下一个话题会涵
12、盖对于内建String机制的兴趣。滞留字符串的优化作用同一个字符串对象被重复地创建是不必要的,String.intern()方法可以避免这种情况。下图说明了String.intern()方法是如何工作的,String.intern()方法检查字符串对象的存在性,如果需要的字符串对象已经存在,那么它会将引用指向已经存在的字符串对象而不是重新创建一个。下图描绘了使用了intern()方法的字符串字面量和字符串对象的创建情况。下面的例程帮助大家了解String.intern()方法的重要性。StringTest2.java/ This class shows the use of intern() method to improve performancepublic class StringTest2 / crea
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1