String 和 StringBuffer区别

JAVA平台提供了两个类:StringStringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据。

这个String类提供了数值不可改变的字符串。而StringBuffer类提供的字符串可以进行修改。


典型地,你可以使用StringBuffers来动态构造字符数据(当字符数据要改变的时候可以使用StringBuffer)。


另外,String实现了equals方法,

new String(abc).equals(new String(abc)的结果为true,

StringBuffer没有实现equals方法,所以,new StringBuffer(abc).equals(new StringBuffer(abc)的结果为false


接着要举一个具体的例子来说明,我们要把1100的所有数字拼起来,组成一个串。

StringBuffer sbf = new StringBuffer();  

for(int i=0;i<100;i++)

{

sbf.append(i);

}

上面代码的效率很高,因为只创建了一个StringBuffer对象,而下面的代码效率很低,因为创建了101个对象。

String str = new String();  

for(int i=0;i<100;i++)

{

str = str + i;

}

在讲两者区别时,应把循环的次数搞成10000,然后用endTime-beginTime来比较两者执行的时间差异,

最后再讲讲StringBuilderStringBuffer的区别。

String覆盖了equals方法和hashCode方法,而StringBuffer没有覆盖equals方法和hashCode方法,

所以,将StringBuffer对象存储进Java集合类中时会出现问题。


扩展:StringBuilderStringBuffer的区别

首先:

java 是 stringbuffer
C#是 stringbuilder

1.  在执行速度方面的比较:StringBuilder >  StringBuffer   
2.  StringBuffer与StringBuilder,他们是字符串变量,是可改变的对象,每当我们用它们对字符串做操作时,实际上是在一个对象上操作的,不像String一样创建一些对象进行操作,所以速度就快了。
3.  StringBuilder:线程非安全的
  StringBuffer:线程安全的
    当我们在字符串缓冲去被多个线程使用是,JVM不能保证StringBuilder的操作是安全的,虽然他的速度最快,但是可以保证StringBuffer是可以正确操作的。当然大多数情况下就是我们是在单线程下进行的操作,所以大多数情况下是建议用StringBuilder而不用StringBuffer的,就是速度的原因。

对于三者使用的总结:1.如果要操作少量的数据用 = String
                    2.单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
                    3.多线程操作字符串缓冲区 下操作大量数据 = StringBuffer
 
StringBuffer与StringBuilder的区别主要是前者是线程安全的,就是说它是同步的;后者不安全,不是同步的,其它的区别不大。当你的程序不需要线程同步,一般都用StringBuilder.

StringBuilder(以下简称sb)与String(以下简称str)的区别是:
举个例子吧:
String s = new String(“woshizifuchuan”);
当你要改变s的时候,比如改为s =s+”dsdsdsd”;
系统会重新创建一个字符串变量它的值为”woshizifuchuandsdsdsd”,然后把该字符串赋值给s.
当你这样的改变s的行为在一个循环里面,那么将会创建大量的中间变量,影响程序的运行效率:如:for(int i=0;i<100000;i++){
s=”a”;
}

StringBuilder sb = new StringBuilder();一次性给sb分配一个固定长度大小的内存空间,当你改变的时候会在此空间后面加上,不够的时候,内存空间自动增加.
比如初始分配的内存大小为10字节,那么.
Sb.append(“as”);它占据内存空间10字节,此时sb.toString().equals(“as”)为true;
Sb.append.(“qqq”),它占据的内存空间还是10字节,sb.toString().equals(“asqqq”)为true.
当内存空间不够的时候,自动加长,加入一次增加10字节,那么:
Sb.append(“ppppppp”),它占据的内存空间为20字节.
StringBuilder允许设定它的初始长度和每次增加的长度。

综合来说:当你大量更一个字符串的时候,String消耗的内存空间小,但是执行效率低。

1.三者在执行速度方面的比较:StringBuilder >  StringBuffer  >  String

  2.String <(StringBuffer,StringBuilder)的原因

    String:字符串常量

    StringBuffer:字符创变量

    StringBuilder:字符创变量

    从上面的名字可以看到,String是“字符创常量”,也就是不可改变的对象。对于这句话的理解你可能会产生这样一个疑问  ,比如这段代码:

1  String s  =   " abcd " ;
2  =  s + 1 ;
3  System.out.print(s); //  result : abcd1

 

       我们明明就是改变了String型的变量s的,为什么说是没有改变呢? 其实这是一种欺骗,JVM是这样解析这段代码的:首先创建对象s,赋予一个abcd,然后再创建一个新的对象s用来    执行第二行代码,也就是说我们之前对象s并没有变化,所以我们说String类型是不可改变的对象了,由于这种机制,每当用String操作字符串时,实际上是在不断的创建新的对象,而原来的对象就会变为垃圾被GC回收掉,可想而知这样执行效率会有多底。

     而StringBuffer与StringBuilder就不一样了,他们是字符串变量,是可改变的对象,每当我们用它们对字符串做操作时,实际上是在一个对象上操作的,这样就不会像String一样创建一些而外的对象进行操作了,当然速度就快了。

  3.一个特殊的例子:

1  String str  =  “This is only a”  +  “ simple”  +  “ test”;
3  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会规规矩矩的按照原来的方式去做。

  4.StringBuilder与 StringBuffer

    StringBuilder:线程非安全的

    StringBuffer:线程安全的

    当我们在字符串缓冲去被多个线程使用是,JVM不能保证StringBuilder的操作是安全的,虽然他的速度最快,但是可以保证StringBuffer是可以正确操作的。当然大多数情况下就是我们是在单线程下进行的操作,所以大多数情况下是建议用StringBuilder而不用StringBuffer的,就是速度的原因。

 

           对于三者使用的总结: 1.如果要操作少量的数据用 = String

                        2.单线程操作字符串缓冲区 下操作大量数据 = StringBuilder

                        3.多线程操作字符串缓冲区 下操作大量数据 = StringBuffer

通俗易懂的说法:

String、StringBuffer和StringBuilder之间最大的区别是String是不可变的对象,而StringBuffer和StringBuilder是可变对象。不可变的意思是【不可变的机制和好处】存储在对象中的值是不变的,下一个问题是:“如果对象是不可变的那么当我想改变对象的内容的时候怎么去更改呢?”准确的说更改后的String对象和更改前的String对象并不是同一个对象。

假设你声明了下边一个String对象:

[java]  view plain copy
  1. String myString = "hello";  
下一步你想在同一个String对象里添加“Guest”,你怎么做呢

[java]  view plain copy
  1. myString = myString + ” Guest”;  

当你打印myString的内容的时候输出的是“Hello Guest”.尽管我们使用的是同一个对象(mySting),在内部却是创建了新的对象,所以,如果对String做类似的操作,比如append、trim等修改String对象的,你实际就是创建了String的新对象。

现在的问题是,这样会导致性能问题吗,答案是肯定的。那么如何使String操作更有效率呢,那就是通过使用StringBuffer和StringBuilder。

因为StringBuffer和StringBuilder对象是可变的,我们可以对存储在对象中的一些值做些改变。这里的有效的意思是和String相比使用StringBuffer和StringBuilder在一些像append等操作上会更有效。

那么StringBuffer和StringBuilder之间又有什么区别呢?

StringBuffer和StringBuilder有着相同的方法,但是StringBuffer是同步的而StringBuilder不是同步的,所以如果你不想使用线程那么使用StringBuilder会更有效(因为这少了同步的开支)。

怎么使用StringBuilder:

首先看看String的方式:

[java]  view plain copy
  1. String s = “Hello”;  
  2. s = s + ” World”;  
  3. system.out.println(s);  

再看一下使用StringBuilder的方式:

[java]  view plain copy
  1. StringBuilder sb = new StringBuilder(“Hello”);  
  2. sb.append(” World”);  
  3. system.out.println(sb);  

下边再运行一个例子来展示String对象是不可变的,来看看下边的代码:

[java]  view plain copy
  1. package com.other.test;  
  2.   
  3. public class StringTest {  
  4.     public static void main(String[] args) {   
  5.         String s = "来一个测试";  
  6.         s.concat("如果是同一个对象,这句话要输出!");  
  7.         System.out.println(s);  
  8.         s = s.concat("如果只输出这句就证明了String是不可变的");  
  9.         System.out.println(s);  
  10.     }  
  11. }  

输出的结果是:

来一个测试

如果只输出这句就证明了String是不可变的

上边的代码证明了String是不可变的,因此像concat这样操作执行的结果是值存储在了新的对象中。

补充一点的是:StringBuilder是java1.5引进来的(如果你是之前的版本那么只能使用StringBuffer)。

关于他们的对比还有两篇好文章:

http://kaioa.com/node/59

http://stackoverflow.com/questions/2971315/string-stringbuffer-and-stringbuilder

展示String是不可变对象的图解:http://www.programcreek.com/2009/02/diagram-to-show-java-strings-immutability/

为什么String是不可变对象:http://www.programcreek.com/2013/04/why-string-is-immutable-in-java/


  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值