Java字符串拼接的方法和性能比较

 字符串的拼接方法一般使用以下五种:

1、String 的加法 "+"

2、String 的concat() 方法

3、StringBuider 的append() 方法

4、StringBuffer 的append() 方法

5、lang3 包中的StringUtils.join() 方法

性能分析: 

方法1:String是final类,是不可变的,所以他一旦被实例化就无法被修改,所以String字符串的拼接,都是又生成了一个新的字符串,使用“+”进行拼接时,反编译出的字节码文件显示先new一个StringBuilder 对象,然后进行append 操作,最后通过toString 方法返回String 对象,该方法适用于小数据量的操作,代码方便简洁,使用该方法更符合我们的编码和阅读习惯

String s1 = "";
s1 += "A";
// 反编译后
s1 = new StringBuilder().append(s1).append("A").toString();

 方法2:concat() 方法实现的源代码如下:

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

 通过源代码可以看出,concat 方法是通过创建一个新的字符数组,然后将原字符串和拼接的字符串的值复制到这个字符数组上,并使用这个字符数组创建一个新的String 对象返回

方法3:StringBuilder 和 StringBuffer 类与String 类不同,它们并不是final 类,所以它们是可以修改的。它们都封装了字符数组,append 方法会将字符直接拷贝到内部的字符数组中,如果字符数组的长度达到最大容量时,就会进行扩容,扩展的容量是当前容量的2倍再加2(可以近似的看作2的N次幂),并且会有未被使用的字符空间,所以,StringBuilder默认分配16个字符的空间,如果能明确字符的最大空间,建议使用如下方式,避免大量的内存空间浪费

new StringBuilder(int size) // 默认分配size个字符的空间

 方法4:StringBuffer 和StringBuilder 最大的区别是该方法使用了synchronized 进行声明,是线程级别安全的方法,该类和StringBuilder 类都是继承自AbstractStringBuilder 类,所以运行效率会比StringBuilder 慢一些

方法5:lang3 包的StringUtils.join() 方法的实现源码如下所示,从以下的源代码可以看出,该方法也是通过StringBuilder 来实实现的,(这里不对该方法做性能比较,理解的朋友看下源代码就知道性能如何了)

    public static <T> String join(T... elements) {
        return join((Object[])elements, (String)null);
    }

    public static String join(Object[] array, String separator) {
        return array == null ? null : join((Object[])array, separator, 0, array.length);
    }

    public static String join(Object[] array, String separator, int startIndex, int endIndex) {
        if (array == null) {
            return null;
        } else {
            if (separator == null) {
                separator = "";
            }

            int noOfItems = endIndex - startIndex;
            if (noOfItems <= 0) {
                return "";
            } else {
                StringBuilder buf = newStringBuilder(noOfItems);

                for(int i = startIndex; i < endIndex; ++i) {
                    if (i > startIndex) {
                        buf.append(separator);
                    }

                    if (array[i] != null) {
                        buf.append(array[i]);
                    }
                }

                return buf.toString();
            }
        }
    }

批量数据处理的比较:

批量数据的处理一般都会用到遍历,对字符串连接应该使用StringBuilder/StringBuffer代替String的连接方式。因为在使用String类拼接字符串时,Java虚拟机不仅要花时间生成对象,以后可能还需要花时间对这些对象进行垃圾回收和处理,因此,生成过多的对象将会给程序的性能带来很大的影响。所以String 不能用来做批量数据的处理。

如下的Demo,数量级十万,从运行时间很明显看出性能如何:

public class Test {

    public static void main(String[] args) {
        String s1 = new String();
        String s2 = new String();
        StringBuilder sb1 = new StringBuilder();
        StringBuffer sb2 = new StringBuffer();
        int num = 100000;

        long t0 = System.currentTimeMillis();
        for (int i = 0; i < num; i++) {
            s1 += "A";
        }
        long t1 = System.currentTimeMillis();

        for (int i = 0; i < num; i++) {
            s2 = s2.concat("a");
        }
        long t2 = System.currentTimeMillis();

        for (int i = 0; i < num; i++) {
            sb1.append("A");
        }
        long t3 = System.currentTimeMillis();

        for (int i = 0; i < num; i++) {
            sb2.append("B");
        }
        long t4 = System.currentTimeMillis();
        System.out.println("String [+]\f"+ (t1 - t0)
                + "\nString [concat()]\f" + (t2 - t1)
                + "\nStringBuilder [append()]\f" + (t3 - t2)
                + "\nStringBuffer [append()]\f" + (t4 - t3));
    }
}

控制台打印如下: 

String [+]    21948
String [concat()]    4179
StringBuilder [append()]     6
StringBuffer [append()]    11

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值