Chinaunix首页 | 论坛 | 博客
  • 博客访问: 88388
  • 博文数量: 61
  • 博客积分: 1401
  • 博客等级: 上尉
  • 技术积分: 810
  • 用 户 组: 普通用户
  • 注册时间: 2009-02-23 15:19
文章分类
文章存档

2010年(2)

2009年(59)

我的朋友

分类: Java

2009-07-09 14:57:04

字符串StringJava编程中使用概率最高的变量,也许你觉得没有什么可讲的,随手拈来,然而字符串的处理却尤其需要我们的关注,因为大量的字符串实例的随意创建,给系统的效率带来了很大的问题。

比如下面我们来做一个测试,对比String类和StringBuffer的执行效率:

     String执行10000次累加

long start = System.currentTimeMillis();

String str = "";

for (int i = 0; i < 10000; i++) {

    str += "," + i;

}

long end = System.currentTimeMillis();

System.out.println(end - start);

执行的结果花费了702ms

     使用StringBuffer类来代替String类:

long start = System.currentTimeMillis();

StringBuffer str = new StringBuffer();

for (int i = 0; i < 10000; i++) {

    str.append(",").append(i);

}

long end = System.currentTimeMillis();

System.out.println(end - start);

运行共花费了0ms

通过对比发现StringBuffer几乎不花费时间。这是因为,String对象的每一次累加,都会先将累加的字符串创建一个实例对象然后再累加,等于是创建了10000个实例。而StringBuffer每次都是修改的原有实例对象,只是创建了1个实例。通过学习第2章我们已经知道,创建实例需要申请内存地址、写入数据的过程,大量的这种操作就会消耗大量的CPU计算资源。

也许你会说,StringBuffer这么高效率,那我们不再使用String类就可以了,然而实际情况是,它们在不同的情况下各有选择的优势。通过《高手真经 Java核心编程技术》第11.2节的讲解可知,StringStringBufferStringBuilder三者最大的区别是:

     String是字符串常量

     StringBuffer是字符串变量(线程安全)

     StringBuilder是字符串变量(非线程安全)

简要的说,String类型和StringBuffer类型的主要性能区别其实在于,String是不可变的对象,因此在每次对String类型进行改变的时候,其实都等同于生成了一个新的String对象,然后将指针指向新的String对象,所以经常改变内容的字符串最好不要用String,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后,JVMGC就会开始工作,那速度是一定会相当慢的。

而如果是使用StringBuffer类则结果就不一样了,每次结果都会对StringBuffer对象本身进行操作,而不是生成新的对象,再改变对象引用。所以在一般情况下我们推荐使用StringBuffer,特别是字符串对象经常改变的情况下。而在某些特别情况下,String对象的字符串拼接其实是被JVM解释成了StringBuffer对象的拼接,所以这些时候String对象的速度并不会比StringBuffer对象慢,而特别是以下的字符串对象生成中,String效率是远要比StringBuffer快的:

String str = “This is only a” + “ simple” + “ test”;

StringBuffer builder = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);

你会很惊讶的发现,生成str对象的速度简直太快了,而这个时候StringBuffer居然速度上根本一点都不占优势。其实这是JVM的一个把戏,实际上:

String str = “This is only a” + “ simple” + “test”;

其实就是:

String str = “This is only a simple test”;

所以不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的String对象的话,速度就没那么快了,譬如:

String str2 = “This is only a”;

String str3 = “ simple”;

String str4 = “ test”;

String str1 = str2 +str3 + str4;

这时候JVM会规规矩矩的按照原来的方式去做。

为了测试这三个类的累加不同次数字符串时的效率,我们编写一个测试类,分别按次数累加字符串:

程序11-8  TestString.java

package test.String;

 

public class TestString {

   

    static int count = 100;//循环次数

   

// 测试String

    public static void testString() {

        long start = System.nanoTime();

        String str = "";

        for (int i = 0; i < count; i++) {

            str += "," + i;

        }

        long end = System.nanoTime();

        System.out.println("String" + (end - start));

    }

   

    // 测试StringBuffer

    public static void testStringBuffer() {

        long start = System.nanoTime();

        StringBuffer str = new StringBuffer();

        for (int i = 0; i < count; i++) {

            str.append(",").append(i);

        }

        long end = System.nanoTime();

        System.out.println("StringBuffer" + (end - start));

    }

   

    // 测试StringBuilder

    public static void testStringBuilder() {

        long start = System.nanoTime();

        StringBuilder str = new StringBuilder();

        for (int i = 0; i < count; i++) {

            str.append(",").append(i);

        }

        long end = System.nanoTime();

        System.out.println("StringBuilder" + (end - start));

    }

 

    public static void main(String[] args) {

        TestString.testString();

        TestString.testStringBuffer();

        TestString.testStringBuilder();

    }

}

运行该程序执行的测试时间:

11-2  测试结果

毫微秒

String

StringBuffer

StringBuilder

1

69,562

46,934

8,101

10

109,791

57,269

24,025

100

431,619

172,089

128,228

1000

8,274,236

876,368

270,985

1万次

704,425,841

2,673,524

1,388,166

10万次

溢出

20,926,961

11,669,361

100万次

溢出

246,871,041

137,586,760

String10w次循环时就溢出了,而StringBuffer100万次循环时间为246msStringBuilder的时间为137ms。显然选择优先级为:StringBuilder>StringBuffer>String。因此,对于这三个类的使用,我们需要按照以下情况去选择:

     如果你偶尔对简单的字符串常量进行拼接,那么可以使用String,它足够简单而且轻量级;

     如果你需要经常进行字符串的拼接、累加操作,请使用StringBufferStringBuilder

     如果是在单线程的环境中,建议使用StringBuilder,它要比StringBuffer快;如果是在多线程的环境中,建议使用StringBuffer,它是线程安全的;

因此,StringBuilder实际上是我们的首选,只有在多线程时才可以考虑使用StringBuffer,只有在字符串的拼接足够简单时才使用String

 

本文出自一书

 

阅读(253) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~