StringBuffer同步,StringBulider不同步,效率高
6 .1.3 StringBuilder 类
一个 String 对象的长度是固定的,不能改变它的内容,或者是附加新的字符至 String 对象中。您也许会使用 + 来串联字符串以达到附加新字符或字符串的目的,但 + 会产生一个新的 String 实例。如果程序对这种附加字符串的需求很频繁,并不建议使用 + 来进行字符串的串联 。在面向对象程序设计中,最好是能重复运用已生成的对象,对象的生成需要内存空间与时间,不断地产生 String 实例是一个没有效率的行为。
J2SE 5.0 提供 java.lang.StringBuilder 类,使用这个类所产生的对象默认会有 16 个字符的长度,您也可以自行指定初始长度。如果附加的字符超出可容纳的长度,则 StringBuilder 对象会自动增加长度以容纳被附加的字符。如果有频繁作字符串附加的需求,使用 StringBuilder 会让程序的效率大大提高。通过下面的简单测试程序就可以知道效能差距有多大。
Ü 范例 6.5 AppendStringTest.java
public class AppendStringTest {
public static void main(String[] args) {
String text = "";
long beginTime = System.currentTimeMillis();
for(int i = 0; i < 10000; i++)
text = text + i;
long endTime = System.currentTimeMillis();
System.out.println(" 执行时间: " + (endTime - beginTime));
StringBuilder builder = new StringBuilder("");
beginTime = System.currentTimeMillis();
for(int i = 0; i < 10000; i++)
builder.append(String.valueOf(i));
endTime = System.currentTimeMillis();
System.out.println(" 执行时间: " + (endTime - beginTime));
}
}
在范例 6.5 中首先使用 + 来串联字符串,使用 System.currentTimeMillis() 取得 for 循环执行前、后的系统时间,这样就可以得知 for 循环执行了多久。以下是我的计算机上的测试数据:
执行时间: 4641
执行时间: 16
可以看到执行的时间差距很大,这说明了使用 + 串联字符串所带来的负担。如果有经常作附加字符串的需求,建议使用 StringBuilder 。事实上就范例 6.5 来说,第二个 for 循环执行时间还可以更短,因为 append() 也可以接受基本数据类型,所以不必特地使用 String.valueOf() 方法从 int 取得 String 。改为以下的方式,执行时间可以大幅缩短:
for(int i = 0; i < 10000; i++)
builder.append(i);
使用 StringBuilder 最后若要输出字符串结果,可以用 toString() 方法。可以使用 length() 方法得知目前对象中的字符长度,而 capacity() 可返回该对象目前可容纳的字符容量。另外, StringBuilder 还有像 insert() 方法可以将字符插入指定的位置,如果该位置以后有字符,则将所有的字符往后移; deleteChar() 方法可以删除指定位置的字符,而 reserve() 方法可以反转字符串。详细的使用可以查询 java.lang.StringBuilder 的 API 文件说明。
StringBuilder 是 J2SE 5.0 才新增的类,在 J2SE 5.0 之前的版本若有相同的需求,则使用 java.lang.StringBuffer 。事实上, StringBuilder 被设计为与 StringBuffer 具有相同的操作接口。在单机非多线程 (Multithread) 的情况下使用 StringBuilder 会有较好的效率,因为 StringBuilder 没有处理同步 (Synchronized) 问题。 StringBuffer 则会处理同步问题,如果 StringBuilder 会在多线程下被操作,则要改用 StringBuffer ,让对象自行管理同步问题。关于多线程的概念,会在第 15 章详细说明。