String

字符串常量,是对象不是原始类型,为不可变对象,一旦被创建,就不能修改它的值。对于已经存在的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去。String 是final类,即不能被继承.

StringBuffer

是一个可变对象,当对他进行修改的时候不会像String那样重新建立对象,另外它只能通过构造函数来建立。StringBuffer是线程安全的。

StringBuilder

是一个可变对象,对使用者来说唯一不同于StringBuffer的是它是非线程安全的。

简要的说,String和StringBuffer类型的主要性能区别在于String是不可变的,因此在每次对String类型进行改变的时候其实都等同于生成了一个新的String对象,然后将指针指向新的String对象,所以经常改变内容的字符串最好不要用String,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后,JVM的GC就会开始工作,那速度是一定会相当慢的。而如果是使用StringBuffer,每次结果都会对StringBuffer对象本身进行操作,而不是生成新的对象,再改变对象引用。所以在字符串对象经常改变的情况下我们推荐使用StringBuffer。

现在的JVM都对String进行了大量的优化,在某些特殊的情况下,String的性能并不会比StringBuffer差,参考下列代码:

String s1= "This is only a" + " simple" + " test";
StringBuffer sb= new StringBuilder("This is only a").append(" simple").append(" test");

你会发现,生成String s1对象的速度简直太快了,这个时候StringBuffer速度上居然不占一点优势。其实在JVM进行优化之后,在JVM眼里,这一行:

String s1 = "This is only a" + " simple" + "test";

等同于:

String s1 = "This is only a simple test";

所以当然不需要太多的时间。但这里要注意的是,如果你的字符串是来自另外的String对象,速度就没那么快了,比如:

String s2 = "This is only a";
String s3 = " simple";
String s4 = " test";
String s1 = s2 +s3 + s4;

这时候JVM只能规规矩矩的按照原来的方式去做,所以只能说大部分情况下在性能上StringBuffer > String。

看看以下代码:

将26个英文字母重复加了5000次:

String tempstr = "abcdefghijklmnopqrstuvwxyz";
int times = 5000;
long lstart1 = System.currentTimeMillis();
String str = "";
for (int i = 0; i < times; i++) {
	str += tempstr;
}
long lend1 = System.currentTimeMillis();
long time = (lend1 - lstart1);
System.out.println(time);

在我的机器上得到的结果每次不一定,一般为46687左右,也就是46秒。

我们再看看以下代码:

String tempstr = "abcdefghijklmnopqrstuvwxyz";
int times = 5000;
long lstart2 = System.currentTimeMillis();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < times; i++) {
	sb.append(tempstr);
}
long lend2 = System.currentTimeMillis();
long time2 = (lend2 - lstart2);
System.out.println(time2);

得到的结果为16有时还是0。

结论很明显,StringBuffer的速度几乎是String上万倍。当然这个数据不是绝对的,根据循环次数的多少会有不同的差异。

根据上面所说:

str += "here";

的处理步骤实际上是通过建立一个StringBuffer,让侯调用append(),最后

再将StringBuffer toSting();

所以str += "here";可以等同于

StringBuffer sb = new StringBuffer(str);

sb.append("here");

str = sb.toString();

所以上面直接利用"+"来连接String的代码可以基本等同于以下代码:

String tempstr = "abcdefghijklmnopqrstuvwxyz";
int times = 5000;
long lstart2 = System.currentTimeMillis();
String str = "";
for (int i = 0; i < times; i++) {
	StringBuffer sb = new StringBuffer(str);
	sb.append(tempstr);
	str = sb.toString();
}
long lend2 = System.currentTimeMillis();
long time2 = (lend2 - lstart2);
System.out.println(time2);

平均执行时间为46922左右,也就是46秒。

总结: 如果在程序中需要对字符串进行频繁的修改连接操作的话.使用StringBuffer性能会更高。

StringBuilder是JDK5.0之后新增加的一个类,此类提供一个与StringBuffer兼容的API,两者的方法基本相同,区别在于它不是线程安全的。该类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候。如果可能,建议优先采用该类,因为在大多数实现中,它比StringBuffer要快。

你可能感兴趣的内容
0条评论

selfly

交流QQ群:32261424
Owner