引言:
关于String,StringBuilder,StringBuffer的问题,在日常开发中似乎并没有引起我们的重视,但是仅仅这个点可能就影响到我们编写的程序的性能,同时这个点也是面试时经常被问到的java基础题。下面我们从理论和实践2个方面来分析和论证3者之间的关系。
一.理论
String,StringBuffer,StringBuilder比较
string字符常量,是属于不可变类,任何对String的修改都会引发新的string对象生成stringBuffer字符变量,线程安全,支持并发操作,单线程下效率比StringBuilder低stringBuilder字符变量,线程不安全,不支持并发操作,不考虑多线程情况下,推荐使用这种方式
二.实践
1. string本质
String s="abc"; s=s+"d"; System.out.println(s);前面我们提到String是“字符创常量”,也就是不可改变的对象,在上面代码中我们明明就是改变了String型的变量s的,为什么说是没有改变呢? 其实这是一种欺骗,JVM是这样解析这段代码的:首先创建对象s,赋予一个abcd,然后再创建一个新的对象s用来执行第二行代码,也就是说我们之前对象s并没有变化,所以我们说String类型是不可改变的对象了,由于这种机制,每当用String操作字符串时,实际上是在不断的创建新的对象,而原来的对象就会变为垃圾被GC回收掉,可想而知这样执行效率会有多底。2.String,StringBuffer,StringBuilder执行速度差异
package test; import org.junit.Test; public class StringTest { public String testcontent="welcome to my blog"; public int testCount=100000; //string测试 public void Stringtest(){ long start=System.currentTimeMillis(); String s=""; for(int i=0;i<=testCount/10;i++) { s=s+testcontent; } long end=System.currentTimeMillis(); long time=end-start; System.out.println("string:"+time+" millis"); } //stringbuffer测试 public void StringBuffertest(){ StringBuffer s=new StringBuffer(); long start=System.currentTimeMillis(); for(int i=0;i<=testCount;i++) { s.append(testcontent); } long end=System.currentTimeMillis(); long time=end-start; System.out.println("stringBuffer:"+time+" millis"); } //stringbuilder测试 public void StringBuildertest(){ StringBuilder s=new StringBuilder(); long start=System.currentTimeMillis(); for(int i=0;i<=testCount;i++) { s.append(testcontent); } long end=System.currentTimeMillis(); long time=end-start; System.out.println("stringBuilder:"+time+" millis"); } } 执行结果如下:stringbuilder:15millis
stringbuffer:16millis
string:1692 millis
三,结论
1.速度比较
三者在执行速度方面的比较:StringBuilder > StringBuffer > String
2.应用场景
String当操作小数据集的字符时可以考虑使用StringBuffer当在多线程环境下建议使用StringBuilder在单线程下,操作大字符串时,或者涉及字符串多次修改,变更操作时使用(推荐)