当前位置: 首页 > 技术随笔 > StringBuilder、StringBuffer与Java字符串处理

StringBuilder、StringBuffer与Java字符串处理

以前经常在网上看到关于Java字符串拼接等方面的讨论。看到有些Java开发人员在给新手程序员的建议中类似如下写道:

不要使用+号拼接字符串,要使用StringBufferStringBuilder的append()方法来拼接字符串。

不过,用+号拼接字符串就真的那么令人讨厌,难道使用+号拼接字符串就没有一点可取之处吗?

通过查阅Java API文档中关于String类的部分内容,我们可以看到如下片段:

Java String API

这段话很明确地告诉我们,在Java中使用+号拼接字符串,实际上使用的就是StringBuffer或StringBuilder及其append方法来实现的。

除了Java API文档,我们还可以使用工具查看class类文件的字节码命令来得到上述答案。 例如代码:

public static void main(String[] args) {
	String a = "Hello";
	String b = " world";
	String str = a + b + " !";
	System.out.println(str);
}

通过工具查看到其对应的字节码命令如下:

javap-command-1

从字节码命令中,我们可以清楚地看到,我们编写的如下代码

String str = a + b + " !";

被编译器转换成了类似如下语句:

String str = new StringBuilder(String.valueOf(a)).append(b).append(" !").toString();

不仅如此,Java的编译器也是一个比较聪明的编译器,当+号拼接的全部是字符串字面量时,Java的编译器将会在编译时智能地将其转换为一个完整的字符串。例如:

public static void main(String[] args) {
	String str = "Hello" + " world" + ", Java!";
	System.out.println(str);
}

Java编译器直接将这种全是字面量的字符串拼接,在编译时就转换为了一个完整的字符串。

java-command-2

就算+号拼接的字符串中存在变量,Java编译器也会将最前面的字符串字面量合并为一个字符串。

public static void main(String[] args) {
	String java = ", Java!";
	String str = "Hello" + " world" + java;
	System.out.println(str);
}

javap-command-3

从上述可知,对于类似String str = str1 + str2 + str3 + str4,这种将多个字符串一次性拼接的操作,使用+号来进行拼接是完全没有问题的。

众所周知,在Java 1.4版本之前,字符串拼接可以使用StringBuffer,从Java 1.5开始,我们可以使用StringBuilder来拼接字符串。StringBuffer和StringBuilder的主要区别在于:StringBuffer是线程安全的,适用于多线程操作字符串;StringBuilder是线程不安全的,适合单线程下操作字符串。不过,我们的大多数字符串拼接操作都是在单线程下进行的,因此使用StringBuilder有利于提高性能。

在Java 1.4之前,编译器使用StringBuffer来处理+号拼接的字符串;从Java 1.5开始,编译器大多数情况下都使用StringBuilder来处理+号拼接的字符串。

当我们在JDK 1.4的环境下编写代码时,对于上述这种一次性拼接多个字符串的情况,建议最好使用+号来处理。这样,当JDK 升级到1.5及以上版本时,编译器将会自动将其转换为StringBuilder来拼接字符串,从而提高字符串拼接效率。

当然,推荐使用+号拼接字符串也仅限于在一条语句中拼接多个字符串时使用。如果分散在多条语句中拼接一个字符串,仍然建议使用StringBuffer或StringBuilder。 例如:

public static void main(String[] args) {
	String java = ", Java!";
	String str = "";
	str += "Hello";
	str += " world";
	str += java;
	System.out.println(str);
}

编译器编译后的字节命令如下:

javap-command-4

从上面的图片中我们可以知道,每一条+号拼接语句,都创建了一个新的StringBuilder对象。这种情况在循环条件下表现得尤其明显,造成了相对较大的性能损耗。因此,在多条语句中拼接字符串,强烈建议使用StringBuffer或StringBuilder来处理。

此外,在使用StringBuffer或StringBuilder的时候,我们还可以使用如下方式,进一步提高性能(下面代码以StringBuilder为例,StringBuffer与此类似)。

1.预测最终获得的字符串的最大长度。

StringBuilder内部char数组的默认长度为16,当我们append追加字符串后超过此长度时,StringBuilder会扩大内部的数组容量以满足需要。在这个过程中,StringBuilder会创建一个新的较大容量的char数组,并将原数组中的数据复制到新数组中。如果我们能够大致预测到最终拼接得到的字符串的最大长度,就可以在创建StringBuilder对象时指定合适大小的初始容量。例如,我们需要拼接获得含有100个字母a的字符串。即可编写如下代码:

StringBuilder sb = new StringBuilder(100);
for (int i = 0; i < 100; i++) {
	sb.append('a');
}
System.out.println(sb);

请根据实际情况进行平衡,以创建适合初始容量的StringBuilder。

2.对于单个字符,尽可能地使用char类型,而不是String类型。

有些时候,我们需要在字符串后追加单个字符(例如:a),此时应尽可能地使用

sb.append('a');

而不是使用:

sb.append("a");

如何反编译Java字节码文件?你可以点击这里查看使用javap反编译Java字节码文件

15 0
我们认为: 用户的主要目的,是为了获取有用的信息,而不是来点击广告的。因此本站将竭力做好内容,并将广告和内容进行分离,确保所有广告不会影响到用户的正常阅读体验。用户仅凭个人意愿和兴趣爱好点击广告。
我们坚信:只有给用户带来价值,用户才会给我们以回报。
CodePlayer技术交流群1CodePlayer技术交流群1

帮朋友打一个硬广告:

P2P网贷系统(Java版本) 新年低价大促销,多年P2P技术积累,系统功能完善(可按需定制,可支持第三方存管、银行存管),架构稳定灵活、性能优异、二次开发快速简单。 另可提供二次开发、安装部署、售后维护、安全培训等一条龙服务。

外行看热闹,内行看门道。可以自信地认为,在系统设计上,比市面上的晓风、迪蒙、方维、绿麻雀、国融信、金和盛等P2P系统要好。
深圳地区支持自带技术人员现场考察源代码、了解主要技术架构,货比三家,再决定是否购买。

也可推荐他人购买,一旦完全成交,推荐人可获得实际售价 10% 的返现。
有意向者,详情请 点击这里 联系,工作时间立即回复。