第51条:当心字符串连接的性能

字符串连接操作符(+)是把多个字符串合并为一个字符串的便利途径。要想产生单独一行的输出,或者构造一个字符串来表示一个较小的、大小固定的对象,使用连接操作符是非常合适的,但是它不适合运用在大规模的场景中。为连接n个字符串而重复地使用字符串连接操作符,需要n的平方级的时间。这是由于字符串不可变而导致的不幸结果。当两个字符串被连接在一起时,他们的内容都要被拷贝。

例如:考虑下面的方法,它通过反复连接每个项目行,构造出一个代表该对账单的字符串。代码如下:

    public String statement(){
        String result = "";
        for (int i = 0; i < numItems; i++ ){
            result += lineForItem(i);
            return result;
        }
    }

如果项目数量巨大,这个方法的执行时间就难以估算。为了获得可以接受的性能,请使用StringBuffer替代String,来存储建筑中的对账单。

    public String statement(){
        StringBuffer sb = new StringBuffer(numItems() * LINE_WIDTH);
        for (int i = 0; i < numItems(); i++ ){
            sb.append(lineForItem(i));
        }
        return sb.toString();
    }

上诉两种做法的性能差别非常大。如果numItems返回100,并且lineForItem返回一个固定长度为80的字符串,在作者的机器上,第二种做法比第一种做法要快85倍(书上的例子用的是StringBuilder)。因为第一种做法的开销随项目数量而呈平方级增加,所以,项目数越大,性能的差别会越显著。

        long start = System.currentTimeMillis();
        String string = "aa";
        for (int i = 0; i < 100000; i++) {
            string += "a";
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);

        long start1 = System.currentTimeMillis();
        StringBuilder sb = new StringBuilder("aa");
        for (int i = 0; i < 100000; i++) {
            sb.append("a");
        }
        long end1 = System.currentTimeMillis();
        System.out.println(end1 - start1);

输出结果:

5110
4

操作的数量越多 ,差距就越明显

总结:不要使用字符串连接操作符来合并多个字符串,除非性能无关紧要。相反,应该使用StringBuffer的append方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容