Menu

三大类库



Java笔试题经常考到“String和StringBuffer的区别”,对于二者区别网上已经有很多,实际应用中也要主要到二者的区别,二者性能的差别很大。本人通过小例子来比较二者性能,效果显著!

一、分析

【北京尚学堂java300集视频教程免费领取:加微信tangniu520666,备注:4】

String类字符串追加

  当我们对字符串进行拼接时,String:是对象不是原始类型.为不可变对象,一旦被创建,就不能修改它的值.对于已经存在的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去.String
是sealed 类,即不能被继承.

 
  string是String类的别名,引用类型,且该类型是只读的,不可修改,当你修改字符串内容时,实际上是创建了另一个新的字符串并将引用指向了它,你可以参考String类型的构造函数说明,就明白错在哪里了。第一条只是创建了一个String类型的数组,并未对其初始化,如果你对该数组中的任一成员使用第二条的方法进行初始化,一样会报错。

     str += “a”;等效于:str = new StringBuffer(str).append(“a”).toString(); 虽然编译器对字符串加号做了优化,它会用StringBuffer的append方法进行追加。再是通过toString方法转换成String字符串的。 它与纯粹的append方法是不同的: 

一是每次都要创建一个StringBuilder对象; 

二是每次执行完毕都要调用toString方法将其转换为字符串。 

  因此,字符串类型的字符追加有可能会消耗大量的时间,因为每次追加完成之后都要return返回一个新的字符串,每次的操作都会创建一个新的String对象,这就是直接使用速度慢下来的原因。 

String:是对象不是原始类型.

StringBuffer的字符串追加

 

   
 StringBuffer:是一个可变对象,当对他进行修改的时候不会像String那样重新建立对象,它只能通过构造函数来建立,StringBuffer
sb = new StringBuffer();它不能直接对其进行赋值操作,sb = “I Hava a
Dream”;//错误,对象被建立以后,在内存中就会分配内存空间,并初始保存一个null.向StringBuffer中赋值的时候可以通过它的append方法.sb.append(“当然的”);

StringBuilder
-> 字符串不可变,长期拼接字符串性能较低
-> Stringbuilder
Append(string);
AppendLine(string);
AppendFormat(“{0}{1}{2}{3}”, 1, “23”, “ab”, true);
ToString();

     所以它必须通过追加的方式进行赋值。它的内部实现代码如下:

 1 public AbstractStringBuilder append(String str){ 
 2     //如果是null值,则把null作为字符串处理 
 3     if(str == null)str = "null"; 
 4  
 5     int len = str.length(); 
 6     //字符串的长度为0,则返回自身 
 7     if(len == 0)return this; 
 8  
 9     int newCount = count + len; 
10     //追加后的字符串组长度是否超过当前值 
11     if(newCount > value.length) 
12         expandCapacity(newCount);//加长,并作数组拷贝 
13     //字符串复制到目标数组 
14     str.getChars(0, len, value, count); 
15     count = newCount; 
16  
17     return this; 
18 } 

在StringBuffer中进行追加时不需要建立新的对象,开辟新的空间,它始终是一个对象,而String
对象是不可变对象,每次操作Sting 都会重新建立新的对象来保存新的值.
这样原来的对象就没用了,就要被垃圾回收.这也是要影响性能的。

为不可变对象,一旦被创建,就不能修改它的值.

二、场景模拟

     
我们使用Stopwatch类分别对这两种情况进行模拟计时,在C#中有一个秒表类:stopwatch,用这个类可以方便的测试一下代码运行时间。

 1 Stopwatch sp=new Stopwatch();
 2 sp.start();
 3 string s="";
 4 for(int i=0;i<100000;i++)
 5 {
 6         s+=i.toString();
 7 }
 8 sp.Stop();
 9 Console.WriteLine(sp.Elapsed);
10 Console.ReadKey();

结果表明:时间花了30多秒 

而对于StringBuilder:

 1 Stopwatch sp=new Stopwatch();
 2  sp.start();
 3  StringBuilder sb=new StringBuilder();
 4  for(int i=0;i<100000;i++)
 5  {
 6          s+=sb.Append(i.toString());
 7  }
 8  sp.Stop();
 9 Console.WriteLine(sp.Elapsed);
10  Console.ReadKey();

结果表明:时间花了0.几秒,相差了两个数量级

 

对于已经存在的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去.

三、结论

当我们的系统性能不临界的时候,string类型的简答追加比较接地气,符合人们通常的写代码的习惯,而当系统性能临界,我们要进行数量级比较大的循环,我们就应该使用StringBuilder,提高我们的代码优化。

 

String 是final类,即不能被继承.

 

StringBuffer:

美高梅开户,是一个可变对象,当对他进行修改的时候不会像String那样重新建立对象

它只能通过构造函数来建立,

StringBuffer sb = new StringBuffer();

对象被建立以后,在内存中就会分配内存空间,并初始保存一个null.通过它的append方法向其赋值.

sb.append;

字符串连接操作中StringBuffer的效率要明显比String高:

String对象是不可变对象,每次操作Sting 都会重新建立新的对象来保存新的值.

StringBuffer对象实例化后,只对这一个对象操作。

我这里写了一个小的例子,来测试String和StringBuffer在时间和空间使用上的差别。

美高梅开户 1

测试结果:

使用String做10000次向一字符串后添加字符串

操作耗时:1872ms,内存消耗:1301KB

使用StringBuffer做10000次向一字符串后添加字符串

操作耗时:15ms,内存消耗:162KB

差别显著!

标签:,

发表评论

电子邮件地址不会被公开。 必填项已用*标注

相关文章

网站地图xml地图