侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130562 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

java 字符串拼接的研究与优化

2022-06-23 星期四 / 0 评论 / 0 点赞 / 61 阅读 / 5036 字

String 在java中是不可变的,每个对String进行操作的方法实际上都是返回一个新的String对象,并使原来的String对象不可达。对String的连接常有下面几种方法,一种是使用‘+’符

String 在java中是不可变的,每个对String进行操作的方法实际上都是返回一个新的String对象,并使原来的String对象不可达。对String的连接常有下面几种方法,一种是使用‘+’符号,另一种是使用StringBuilder,再就是String的concat方法。

(1) ‘+’:

为了研究'+'的实现,我们写以下测试代码:

public static void main(String[] args) {	String a="hell"+"o";   //code1	String b="world";	for(int i=0;i<4;i++) {	   a+=b;             //code2	}}
把上面代码编译后再用jdk的反编译工具(javap)反编译下,得到如下代码:
public static void main(java.lang.String[]);  Code:   0:    ldc    #16; //String hello   2:    astore_1   3:    ldc    #18; //String world   5:    astore_2   6:    iconst_0   7:    istore_3   8:    goto    33   11:    new    #20; //class java/lang/StringBuilder   14:    dup   15:    aload_1   16:    invokestatic    #22; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;   19:    invokespecial    #28; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V   22:    aload_2   23:    invokevirtual    #31; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;   26:    invokevirtual    #35; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;   29:    astore_1   30:    iinc    3, 1   33:    iload_3   34:    iconst_4   35:    if_icmplt    11   38:    return
从code1可以得到“如果在‘+’左右没有变量的时候,‘+‘的结果是直接得出的。

从code2可以得到,如果在‘+’左右有变量的时候,会生成一个StringBuilder对象,然后调用其append方法。

在一个拼接String的语句中,如果被拼接的String中有String对象,那这个语句会生成一个StringBuilder对象,然后调用其append方法.

注意源码中的循环,反编译后在代码中对应的是<line>8</line>到<line>35</line>,而创建StringBuilder对象被包含在了循环内,所以上面的代码会创建过多StringBuilder对象而影响效率。

(2) StringBuilder

下面我们来分析下StringBuilder的append方法,其源码如下:

public StringBuilder append(String str) {	super.append(str);        return this;    }
super.append(str)如下:
public AbstractStringBuilder append(String str) {	if (str == null) str = "null";        int len = str.length();	if (len == 0) return this;	int newCount = count + len;	if (newCount > value.length)	    expandCapacity(newCount);//此方法拓展StringBuilder的容量至当前容量的2倍	str.getChars(0, len, value, count);	count = newCount;	return this;    }
通过分析源码我们可以发现StringBuilder的效率是很高的(这也是java编译器默认采用StringBuilder的原因),但要注意拓展容量的操作,所以适当设置初始容量是很有必要的。

(3)String的concat方法

其源码如下:

public String concat(String str) {	int otherLen = str.length();	if (otherLen == 0) {	    return this;	}	char buf[] = new char[count + otherLen];	getChars(0, count, buf, 0);	str.getChars(0, otherLen, buf, count);	return new String(0, count + otherLen, buf);    }

这个方法的作用很简单,就是创建一个新String对象。

结论:

定义三个变量:String a="a",b="b",c="c";

1.对于简单拼接,如String d=a+b,建议使用concat方法:String d=a.concat(b);来减少生成不必要的StringBuilder对象

2.对于二次以上拼接,如String d=a+b+c,使用这种方式就可以

3.对于涉及到循环的拼接,如:

String d="";String e="";for(int i=0;i<10;i++) {   d+=a;//或d=d+a;   e+=(a+b);//或e=e+a+b;}

建议采用以下方式:

StringBuilder d = new StringBuilder(10)//设置初始容量以减少拓容操作StringBuilder e = new StringBuilder(20);for(int i=0;i<10;i++) {  d.append(a);  e.append(a).append(b);}
#本文参考自《thinking in java》第四版Strings章节

广告 广告

评论区