`
T240178168
  • 浏览: 368026 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

StringBuffer和String的区别

    博客分类:
  • java
阅读更多
java.lang.StringBuffer线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。

可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。

StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。 append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。

例如,如果 z 引用一个当前内容是“start”的字符串缓冲区对象,则此方法调用 z.append("le") 会使字符串缓冲区包含“startle”,而 z.insert(4, "le") 将更改字符串缓冲区,使之包含“starlet”。

通常,如果 sb 引用 StringBuilder 的一个实例,则 sb.append(x) 和 sb.insert(sb.length(), x) 具有相同的效果。

只要发生有关源序列(如在源序列中追加或插入)的操作,该类就只在执行此操作的字符串缓冲区上而不是在源上实现同步。

每个字符串缓冲区都有一定的容量。只要字符串缓冲区所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区数组。如果内部缓冲区溢出,则此容量 自动增大。从 JDK 5 开始,为该类补充了一个单个线程使用的等价类,即 StringBuilder。与该类相比,通常应该优先使用 StringBuilder 类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。

java.lang.StringBuilder一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。

在 StringBuilder 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串生成器中。 append 方法始终将这些字符添加到生成器的末端;而 insert 方法则在指定的点添加字符。

例如,如果 z 引用一个当前内容为“start”的字符串生成器对象,则该方法调用 z.append("le") 将使字符串生成器包含“startle”,而 z.insert(4, "le") 将更改字符串生成器,使之包含“starlet”。

通常,如果 sb 引用 StringBuilder 的实例,则 sb.append(x) 和 sb.insert(sb.length(), x) 具有相同的效果。 每个字符串生成器都有一定的容量。只要字符串生成器所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区。如果内部缓冲区溢出,则此容量自动 增大。

将 StringBuilder 的实例用于多个线程是不安全的。如果需要这样的同步,则建议使用 StringBuffer。


String的创建
   String s = "hello";
   JVM先根据内容"hello"查找对象,如果没有找到,则在heap上创建新对象,并将其赋予s1,否则使用已经存在的对象
   String s = new String("hello");
   JVM直接在heap上创建新的对象,所以在heap中会出现内容相同,地址不同的String对象
"hello"就是一个对象
因此才可以
String s1="hello";
才可以
String s2=new String("hello");

String的比较
   "=="         比较地址
   "equals"     比较内容
==是判断两个变量或实例是不是指向同一个内存空间,即引用
equals是判断两个变量或实例所指向的内存空间的值是不是相同
   举例:
   String s1 = "hello";
   String s2 = "hello";
   String s3 = new String("hello");
   s1 == s2;                 // true         地址相同
   s1 == s3;                 // false         地址不同
   s1.equals(s2);           // true         内容相同
   s1.equals(s3);           // true         内容相同

intern() 方法
     查找内容相同(equals())的字符串
     String s1 = "hello";                 // hello不存在,jvm创建新对象 (1)
     String s2 = new String("hello");     // 创举新对象 (2),这时heap中存在两个内容为hello的对象
     s1 == s2;             // false         // 地址不同
     s1.equals(s2);       // true           // 内容相同
     s2 = s1.intern();     // true           // 找到对象(1) 并赋予s2
     s1 == s2;             // true !!       // 注意:此时s1,s2同指向(1)

效率: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). 简单的认为 .append() 效率好于 "+" 是错误的!
     2). 不要使用 new 创建 String
     3). 注意 .intern() 的使用
     4). 在编译期能够确定字符串值的情况下,使用"+"效率最高
     5). 避免使用 "+=" 来构造字符串
     6). 在声明StringBuffer对象的时候,指定合适的capacity,不要使用默认值(18)
     7). 注意以下二者的区别不一样
         - String s = "a" + "b";
         - String s = "a";
           s += "b";
我觉得说String的字符串不能改变话是不错,但是例子要举好

看看下面这个简单的例子:
首先,


public class xx {public static void main(String[] args) { String s1 = "You are hired!";String s2 = "You are hired!";if (s1==s2) {System.out.println("一个内存空间");} else {System.out.println("不是一个内存空间");}}}
打印的结果是:一个内存空间
这里==的意义是两个操作数是否指向同一个对象
可见s2在不用new创建的情况下会自动检索到具有相同内容的内存空间中共享,那么既然s1和s2共享了同一个对象
再看下面的代码


public class xx {public static void main(String[] args) { String s1 = "You are hired!";String s2 = "You are hired!";s1 = s1.replace('h','f');System.out.println(s1);if (s1==s2) {System.out.println("一个内存空间");} else {System.out.println("不是一个内存空间");}}}
代码结果是
You are fired!
不是一个内存空间
可见,String中s1的内容虽然被改写,但是已经不在是原来第一次分配到的那个内存空间,也就是String类的内容能被改变,但一旦改变系统将为其分配新的内存
说到与stringBuffer的区别,从根本上来说应该是
stringBuffer在做字符长度变动的时候将继续使用原来的内存空间,不新分配.
而String的长度一旦变动,就如上面的例子一样,其内部将分配新的内存空间.  

在java中有3个类来负责字符的操作。
1.Character 是进行单个字符操作的,
2.String 对一串字符进行操作。不可变类。
3.StringBuffer 也是对一串字符进行操作,但是可变类。
String:
是对象不是原始类型.
为不可变对象,一旦被创建,就不能修改它的值.
对于已经存在的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去.
String 是final类,即不能被继承.
StringBuffer:
是一个可变对象,当对他进行修改的时候不会像String那样重新建立对象
它只能通过构造函数来建立,
StringBuffer sb = new StringBuffer();
note:不能通过付值符号对他进行付值.
sb = "welcome to here!";//error
对象被建立以后,在内存中就会分配内存空间,并初始保存一个null.向StringBuffer
中付值的时候可以通过它的append方法.
sb.append("hello");
字符串连接操作中StringBuffer的效率要比String高:
String str = new String("welcome to ");
str += "here";
的处理步骤实际上是通过建立一个StringBuffer,让侯调用append(),最后
再将StringBuffer toSting();
这样的话String的连接操作就比StringBuffer多出了一些附加操作,当然效率上要打折扣.
并且由于String 对象是不可变对象,每次操作Sting 都会重新建立新的对象来保存新的值.
这样原来的对象就没用了,就要被垃圾回收.这也是要影响性能的.
看看以下代码:
将26个英文字母重复加了5000次,

String tempstr = "abcdefghijklmnopqrstuvwxyz";
int times = 5000;
long lstart1=System.currentTimeMillis();
   String str ="";
   for(int i=0;i<times;i++)
   {
     str+=tempstr;
   }

   long lend1=System.currentTimeMillis();
   long time = (lend1-lstart1);
   System.out.println(time);

可惜我的计算机不是超级计算机,得到的结果每次不一定一样一般为 154735 左右。
也就是154秒。
我们再看看以下代码

String tempstr = "abcdefghijklmnopqrstuvwxyz";

   int times = 5000;
long lstart2=System.currentTimeMillis();
   StringBuffer sb =new StringBuffer();
   for(int i=0;i<times;i++)
   {
     sb.append(tempstr);

   }
   long lend2=System.currentTimeMillis();
   long time2 = (lend2-lstart2);
   System.out.println(time2);
得到的结果为 16 有时还是 0
所以结论很明显,StringBuffer 的速度几乎是String 上万倍。当然这个数据不是很准确。因为循环的次数在100000次的时候,差异更大。不信你试试。
总结: 如果在程序中需要对字符串进行频繁的修改连接操作的话.使用StringBuffer性能会更高 


String和StringBuffer的区别,网上资料可以说是数不胜数,但是看到这篇文章,感觉里面做的小例子很有代表性,所以转一下,并自己做了一点总结。

在java中有3个类来负责字符的操作。

1.Character 是进行单个字符操作的,

2.String 对一串字符进行操作。不可变类。

3.StringBuffer 也是对一串字符进行操作,但是可变类。

String:

是对象不是原始类型;为不可变对象,一旦被创建,就不能修改它的值;对于已经存在的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去;String 是final类,即不能被继承。


StringBuffer:

是一个可变对象,当对他进行修改的时候不会像String那样重新建立对象;它只能通过构造函数来建立(StringBuffer sb = new StringBuffer());不能通过付值符号对他进行付值(如:sb = "welcome to here!";//这样是错误的);对象被建立以后,在内存中就会分配内存空间,并初始保存一个null.向StringBuffer中付值的时候可以通过它的append方法(如:sb.append("hello"))。


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

eg:
String str = new String("welcome to ");
str += "here";

其处理步骤实际上是通过建立一个StringBuffer,然后调用append(),最后
再将StringBuffer.toSting();这样的话String的连接操作就比StringBuffer多出了一些附加操作,当然效率上要打折扣。

并且由于String 对象是不可变对象,每次操作Sting 都会重新建立新的对象来保存新的值.
这样原来的对象就没用了,就要被垃圾回收.这也是要影响性能的。

总结: 如果在程序中需要对字符串进行频繁的修改连接操作的话.使用StringBuffer性能会更高。

另一处转载:

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

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

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

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

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

       String S1 = “This is only a” + “ simple” + “test”; 其实就是:

       String S1 = “This is only a simple test”; 所以当然不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的 String 对象的话,速度就没那么快了,譬如:

String S2 = “This is only a”;

String S3 = “ simple”;

String S4 = “ test”;

String S1 = S2 +S3 + S4;

这时候 JVM 会规规矩矩的按照原来的方式去做, S1 对象的生成速度就不像刚才那么快了,一会儿我们可以来个测试作个验证。

在大部分情况下    StringBuffer > String

StringBuilder 是 JDK5.0 中新增加的一个类,它跟 StringBuffer 的区别看下面的介绍(来源 JavaWorld ):

Java.lang.StringBuffer 线程安全的可变字符序列。类似于 String 的字符串缓冲区,但不能修改。可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。

       每个字符串缓冲区都有一定的容量。只要字符串缓冲区所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区数组。如果内部缓冲区溢出,则此容量自动增大。从 JDK 5.0 开始,为该类增添了一个单个线程使用的等价类,即 StringBuilder 。与该类相比,通常应该优先使用 StringBuilder 类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。

但是如果将 StringBuilder 的实例用于多个线程是不安全的。需要这样的同步,则建议使用 StringBuffer 。


在大部分情况下    StringBuilder > StringBuffer

因此,根据这个不等式的传递定理: 在大部分情况下

StringBuilder > StringBuffer > String
分享到:
评论

相关推荐

    StringBuffer和String_区别

    ### StringBuffer与String的区别详解 #### 一、概念与特性 **String** 是 Java 中一个不可变的类,代表了字符序列。一旦一个 String 对象被创建后,其内容就不能被改变。这使得 String 类非常适合用来表示常量或者...

    String StringBuffer和StringBuilder区别之源码解析

    "String StringBuffer和StringBuilder区别之源码解析" 在Java中,字符串是我们经常使用的数据类型,而String、StringBuffer和StringBuilder是Java中三种常用的字符串类。在这篇文章中,我们将从源码角度对String、...

    String、StringBuilder和StringBuffer的区别

    在Java编程语言中,String、StringBuilder和StringBuffer都是用来处理字符串的类,它们之间存在一些重要的区别,主要涉及到性能和线程安全性。 首先,`String`类代表的是字符串常量,一旦创建,其内容就不能改变。...

    String、StringBuffer与StringBuilder之间区别

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

    String及StringBuffer和StringBuilder的区别

    String、StringBuffer 和 StringBuilder 是 Java 语言中三种不同类型的字符串处理方式,它们之间存在着明显的性能和线程安全性差异。 String String 类型是不可变的对象,每次对 String 对象进行改变时都会生成一...

    stringbuffer和string的区别.pdf

    在Java编程语言中,字符串处理是常见的需求,而对于字符串的操作,Java提供了两个常用类:String和StringBuffer。虽然两者都用于处理文本数据,但它们在实现和性能上有着本质的区别。 首先,String类是不可变的。这...

    String和StringBuffer的区别

    在Java编程语言中,`String`和`StringBuffer`都是用来表示和操作字符串的重要类,但它们在性能和使用场景上有显著的区别。 首先,`String`类是不可变的,这意味着一旦创建了一个`String`对象,它的内容就不能改变。...

    String 和StringBuffer的区别

    从非常细致的角度分析了String和Stringbuffer的主要区别

    源码string和stringbuffer

    针对String的详细介绍针对String的详细介绍针对String的详细介绍针对String的详细介绍针对String的详细介绍针对String的详细介绍针对String的详细介绍针对String的详细介绍针对String的详细介绍针对String的详细介绍...

    String ,StringBuffer与StringBuilder

    在 Java 中,String, StringBuffer 和 StringBuilder 三个类都是用于字符操作的,但它们之间有着很大的区别。 首先,String 是不可变类,意味着一旦创建了 String 对象,就不能修改它的值。每次对 String 对象的...

    string和StringBuffer的区别

    在Java编程语言中,`String`和`StringBuffer`都是用来表示和操作字符串的重要类,但它们在使用场景和性能上有显著的区别。了解这些差异对于编写高效、优化的代码至关重要。 首先,`String`类是不可变的。这意味着...

    string与stringbuffer的区别

    字符串在Java中的表现形式主要有两种:`String`和`StringBuffer`(或者`StringBuilder`)。它们之间的主要区别在于可变性、性能和使用场景。 1. **不可变性**: `String`类是不可变的,这意味着一旦创建了一个`...

    javaString 和StringBuffer的区别

    JAVA平台提供了两个类:String和StringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据.这个String类提供了数值不可改变的字符串.而这个StringBuffer类提供的字符串进行修改.当你知道字符数据要改变的时候...

    java面试笔试题String 和StringBuffer的区别

    综上所述,理解`String`与`StringBuffer`之间的区别以及它们各自的适用场景,对于开发出高效、健壮的Java应用程序至关重要。在面试或笔试中,能够清晰地阐述这两个类的特点及其使用场合,将展现出你对Java基础概念的...

    String、StringBuffer、StringBuilder的使用方法

    在Java编程语言中,`String`、`...理解`String`、`StringBuffer`和`StringBuilder`的区别和使用场合,可以帮助开发者写出更高效、更安全的代码。在实际开发中,应根据项目需求和环境选择合适的字符串处理类。

    String与StringBuffer区别详解

    在Java编程语言中,`String`和`StringBuffer`(在Java 5之后被`StringBuilder`取代,但在多线程环境中仍然使用`StringBuffer`)是处理文本字符串的两个核心类,它们各自有着不同的特性和用途。理解它们的区别对于...

    Java软件开发实战 Java基础与案例开发详解 9-2 StringBuffer和String Builder类共9页.pdf

    ### Java软件开发实战:StringBuffer和StringBuilder类 #### 1. 概述 在Java编程中,处理字符串是一项常见的需求。对于需要频繁修改的字符串,使用`String`类可能会导致性能问题,因为每次修改都会创建一个新的`...

    String总概况及其特性并与StringBuffer的区别详解

    ### String总概况及其特性并与StringBuffer的区别详解 在Java编程语言中,`String`与`StringBuffer`是非常重要的数据类型,被广泛应用于处理文本数据。本文将深入探讨这两个类的基本特性以及它们之间的区别。 ####...

Global site tag (gtag.js) - Google Analytics