`
z_jq1015
  • 浏览: 29603 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

String,new String,StringBuffer的优化思考

JVM 
阅读更多
java.lang.String类对大家来说最熟悉不过了,我们写java程序很少能不用String的。本文讲述如何正确的使用String,内容主要涉及初始化、串联和比较等操作。
    首先我们必须清楚的一点是String类是final类型的,因此你不可以继承这个类、不能修改这个类。我们使用String的时候非常简单,通常都是 String s = "hello",但是Java API中同时提供了一个构造函数为String(String s),因此你也可以这样使用String s = new String("hello",对于后面这样初始化一个String的方式是不推荐的,因为new操作符意味着将会在heap上生成一个新的对象,如果这样的操作发生在一个循环中,那么代价是惨重的。比如
for(int i = 0;i<1000;i++)
{
    String s = new String("hello";
}
这将会创建1000个String类型的对象,由于String类是final的,因此这样的操作事实上是每次都生成了一个新的String对象的。如果你使用String s = "hello";那么就可以实现复用了。
   看这两条语句:
   String   password="ok";
   String   password=new   String("ok";  
   不同的是,第一条现在内存中创建了"ok"这个String,然后将reference赋给password,如果这个时候还有一条语句String pwd = "ok";那么JVM将不再创建"ok",而是直接将第一个"ok"的reference赋给pwd,也就是说,password和pwd是使用同一块内存,而如果加上String   pwd   =   new   String("ok";那JVM将在内存中再创建一块区域放上“ok”这个字符串。
    通常对String的比较有两种情况,一个是使用==,另一个是使用equals()方法,注意==是对对象的地址进行比较的,而String中的 equals()方法是覆盖了Object类的方法,并且实现为对String对象的内容的比较。所以String s1 = new String("hello";String s2 = new String("hello",我们对s1和s2进行上述比较的时候,前者应该返回false,因为使用new生成的是两个不同的对象。后者应该返回 true因为他们的内容是一样的,都是"hello"。那么如果我们还有一个String s3 = "hello";他和s1的比较应该是什么样子的呢,答案是s1==s3为false,equals的比较位true。事实上String类是维持着一个 String池的,这个池初始化为空的,当我们String x = "hello"的时候,hello就会被放入这个池中,当我们再次String y = "hello"的时候,他首先去检查池中是否存在一个和hello内容一样的对象,如果存在的话就会把这个引用返回给y,如果不存在的话,就会创建一个并放入到池中。这样就实现了复用。在String有一个方法intern()他可以把String的对象放入到池冲并返回池中的对象。如果我们对s1 (String s1 = new String("hello")调用intern,s1 = s1.intern()这时候,我们再把s1和s3进行“==”的判断,你会发现结果返回true!

   String是一个final Class,StringBuffer不是。所以对于 String a = "yacht" ,String b = "yacht1" String c = a + b ; 存在一个对象拷贝构造和解析的消耗问题;对于一个StringBuffer来说,StringBuffer sb = new StringBuffer();sb.append("yacht" ; sb.append("yacht1"; 因为StringBuffer是一个可以实例化的类,而且它的内建机制是维护了一个capacity大小的字符数组,所以它的append操作不存在对象的消耗问题,所以我觉得如果存在String连接这种事情,StringBuffer来做会好很多。
    但事情并不是这么简单,看下面代码
    String a = "yacht1" + "yacht2" + "yacht3" + "yacht4";
    StringBuffer sb = new StringBuffer();
    sb.append("yacht1";
    sb.append("yacht2";
    sb.append("yacht3";
    sb.append("yacht4";
    String a = sb.toString();
    如果按照我先前说的看法,第一个效率肯定比第二个低,但经过测试不是这样,为什么?这里,我们需要理解程序过程的两个时期,一个是编译时,一个是运行时,在编译时,编译器会对你的程序做出优化,所以第一个的String a会被优化成yacht1yacht2yacht3yacht4,而第二个的StringBuffer只会在运行时才处理。所以效率是不一样的。
    如果代码是这样的:
    String a ;
    for(int i = 0; i< 100000;i++)
      a += String.valueOf(i);
     StringBuffer sb = new StringBuffer();
    for(int i = 0; i< 100000;i++)
     sb.append(i) ;
    String a = sb.toString();
    如果是这种情况的话,第一个的效率就大大不如蓝色,区别在哪里,就在于运行时和编译时的优化问题上!

效率:String 与 StringBuffer

    情景1:
    (1) String result = "hello" + " world";
    (2) StringBuffer result = new String().append("hello".append(" world";

        (1) 的效率好于 (2),不要奇怪,这是因为JVM会做如下处理
        编译前   String result = "hello" + " world";
        编译后   String result = "hello world";

    情景2:
    (1) public String getString(String s1, String s2) {
            return s1 + s2;
        }
    (2) public String getString(String s1, String s2) {
            return new StringBuffer().append(s1).append(s2);
        }

        (1) 的效率与 (2) 一样,这是因为JVM会做如下处理
        编译前   return s1 + s2;
        编译后   return new StringBuffer().append(s1).append(s2);

    情景3:
    (1) String s = "s1";
              s += "s2";
              s += "s3";
    (2) StringBuffer s = new StringBuffer().append("s1".append("s2".append("s3";

        (2) 的效率好于(1),因为String是不可变对象,每次"+="操作都会造成构造新的String对象

    情景4:
    (1) StringBuffer s = new StringBuffer();
        for (int i = 0; i < 50000; i ++) {
            s.append("hello";
        }
    (2) StringBuffer s = new StringBuffer(250000);
        for (int i = 0; i < 50000; i ++) {
            s.append("hello";
        }  
        (2) 的效率好于 (1),因为StringBuffer内部实现是char数组,默认初始化长度为16,每当字符串长度大于char
        数组长度的时候,JVM会构造更大的新数组,并将原先的数组内容复制到新数组,(2)避免了复制数组的
1
0
分享到:
评论

相关推荐

    String和StringBuffer专题

    使用字符串字面量而不是使用new关键字来创建字符串。 大多数情况下字符串是在运行期决定的,使用一个合适的初期容量值初始化的StringBuffer会为字符串连接提供最佳的性能。

    txt文档转化为String

    StringBuffer content = new StringBuffer(""); //文档内容 try { FileReader reader = new FileReader(path); BufferedReader br = new BufferedReader(reader); String s1 = null; while((s1 = br...

    java io读取文件到String

    StringBuffer sb = new StringBuffer((int)f.length()); while( (line = br.readLine() ) != null ) { sb.append(line).append(LINE_BREAK); } ret = sb.toString(); } finally { if(br!=null) {try{br.close...

    Java StringBuffer & StringBuilder.pdf

    StringBuffer sb = new StringBuffer(); // 向StringBuffer对象中添加字符串 sb.append("Hello"); sb.append(" "); sb.append("World"); // 将StringBuffer对象转换为String对象 String str = sb.toString(); ...

    JavaScript中String和StringBuffer的速度之争

    StringBuffer.js 代码如下: function StringBuffer(){ this.content = new Array; } StringBuffer.prototype.append = function( str ){ this.content.push( str ); } StringBuffer.prototype.toString = function...

    java md5 jar

    StringBuffer buf = new StringBuffer(); try { MessageDigest md5 = MessageDigest.getInstance("MD5"); md5.update(str.getBytes()); byte bytes[] = md5.digest(); for(int i = 0; i ; ...

    校园管理系统

    StringBuffer sb = new StringBuffer(); String initDay = day + " "; for (String time : timeList) { sb.append(initDay); sb.append(time); resultList.add(sb.toString()); sb.delete(0, sb.length())...

    StringBuffer:C 字符串缓冲区

    StringBuffer *sb = string_buffer_new(); string_buffer_append (sb, " hello " ); string_buffer_append_n (sb, " 123456 " , 3 ); string_buffer_appendf (sb, " d " , 10 ); string_buffer_append_set (sb, ' A ...

    利用Java代码实现无字符+中文转换为全中文的代码

    StringBuffer sb2 = new StringBuffer(); //得到当前文件的编码 String ch=getCharset(inputfile); InputStreamReader isr=null; OutputStreamWriter osw =null; //根据当前文件编码进行解码 if(ch.equals...

    Java中反转功能的的实现

    package day13; import java.util.Scanner; /* * 反转功能 * */ public class Day13StringBuffer09 { ...// StringBuffer sb = new StringBuffer(s); // sb.reverse(); // return sb.toString(); // } }

    java写的将字符串中的中文转化为拼音等一系列方法

    StringBuffer pybf = new StringBuffer(); char[] arr = chinese.toCharArray(); HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat(); defaultFormat.setCaseType(HanyuPinyinCaseType....

    神级压缩方法

    }}class MyWindow extends Frame implements ActionListener{ StringBuffer m=new StringBuffer(); int p; TextField tex; Button b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,jia,jian,cheng,chu,deng,dian,qingling,kaifang;...

    汉字转换成中文拼音pinyin4j-2.5.0.jar

    StringBuffer strBuf = new StringBuffer(); byte[] bGBK = cnStr.getBytes(); for(int i=0;i ;i++){ strBuf.append(Integer.toHexString(bGBK[i]&0xff;)); } return strBuf.toString(); } public static ...

    sql访问数据库工具类--SqlUtils(java源码)

    StringBuffer buffer = new StringBuffer(); if (!propertyMap.isEmpty() && propertyMap.size() &gt; 0) { buffer.append("WHERE 1 = 1 "); int index = 0; for (String property : propertyMap.keySet()...

    java验证回文字符串工具类

    StringBuffer sb = new StringBuffer(str); sb.reverse();// 把字符串反转 int count = 0; for (int i = 0; i (); i++) { if (str.charAt(i) == sb.charAt(i)) { count++; //统计相同字符的个数 } } if ...

    JAVA精华.rar

    String x=”a” 4 ”c”编译时等效于String x=new StringBuffer().append(“a”).append(4).append(“c”).toString(); 字符串常量是一种特殊的匿名对象,String s1=”hello”;String s2=”hello”;则s1==s2;因为...

    Java文件处理工具类--FileUtil

    StringBuffer out = new StringBuffer(); for (int i = 0; i (); i++) { char ch = fileName.charAt(i); // Replace invlid chars: \\/:*?\"| switch (ch) { case '\\': case '/': case ':':...

    java笔试题目

    java笔试题目

    50个Java面试题.pdf

    50个Java面试题.pdf

    c_string_buffer:一个简单的C字符串缓冲区

    string_buffer C的简单字符串缓冲区。 概述 该库提供了一个简单的字符串缓冲区,该缓冲区... struct StringBuffer *buffer = string_buffer_new_with_options ( 1024 , // initial size true // allow resizing )

Global site tag (gtag.js) - Google Analytics