Java中String和StringBuffer有什么区别?

字符串有最大大小吗?

有帮助吗?

解决方案

String 用于操作不能更改的字符串(只读且不可变)。

StringBuffer 用于表示可以修改的字符。

性能方面, StringBuffer 执行串联时速度更快。这是因为当您连接一个 String, ,从那时起,您每次都会(内部)创建一个新对象 String 是不可变的。

您还可以使用 StringBuilder 这类似于 StringBuffer 除非它不同步。其中任何一个的最大尺寸是 Integer.MAX_VALUE (231 - 1 = 2,147,483,647)或最大堆大小除以 2(请参阅 Java字符串可以有多少个字符?)。更多信息 这里.

其他提示

一个String是不可变的,即,它的创建时,它可以永远不会改变。

当你需要构造由一块串片而不沿途构建许多小StringBuffers的的性能开销甲StringBuilder(或它的非同步表妹String)被使用。

两者的最大长度为Integer.MAX_VALUE的,因为它们在内部存储为阵列,和Java阵列只对它们的长度的伪字段的int

Strings之间StringBuffers的性能改进为多个级联是相当显著。如果您运行下面的测试代码,你会看到其中的差别。在我的旧笔记本电脑与Java 6中,我得到这些结果:

Concat with String took: 1781ms
Concat with StringBuffer took: 0ms
public class Concat
{
    public static String concatWithString()
    {
        String t = "Cat";
        for (int i=0; i<10000; i++)
        {
            t = t + "Dog";
        }
        return t;
    }
    public static String concatWithStringBuffer()
    {
        StringBuffer sb = new StringBuffer("Cat");
        for (int i=0; i<10000; i++)
        {
            sb.append("Dog");
        }
        return sb.toString();
    }
    public static void main(String[] args)
    {
        long start = System.currentTimeMillis();
        concatWithString();
        System.out.println("Concat with String took: " + (System.currentTimeMillis() - start) + "ms");
        start = System.currentTimeMillis();
        concatWithStringBuffer();
        System.out.println("Concat with StringBuffer took: " + (System.currentTimeMillis() - start) + "ms");
    }
}
String                                          StringBuffer

Immutable                                       Mutable
String s=new String("karthik");                StringBuffer sb=new StringBuffer("karthik")
s.concat("reddy");                             sb.append("reddy");
System.out.println(s);                         System.out.println(sb);
O/P:karthik                                    O/P:karthikreddy

--->once we created a String object            ---->once we created a StringBuffer object
we can't perform any changes in the existing  we can perform any changes in the existing
object.If we are trying to perform any        object.It is nothing but mutablity of 
changes with those changes a new object       of a StrongBuffer object
will be created.It is nothing but Immutability
of a String object

Use String--->If you require immutabilty
Use StringBuffer---->If you require mutable + threadsafety
Use StringBuilder--->If you require mutable + with out threadsafety

String s=new String("karthik");
--->here 2 objects will be created one is heap and the other is in stringconstantpool(scp) and s is always pointing to heap object

String s="karthik"; 
--->In this case only one object will be created in scp and s is always pointing to that object only

的字符串是一个不可变的类。这意味着,一旦实例化的字符串的一个实例如下所示:

String str1 = "hello";

在存储器中的对象不能被改变。相反,你必须创建一个新的实例,复制旧字符串并追加其他任何在这个例子:

String str1 = "hello";
str1 = str1 + " world!";

什么是真正发生的听到的是,我们并没有更新现有STR1对象......我们正在重新分配新的内存都在一起,复制“你好”的数据并追加“的世界!”到最后,然后设置其中str1参考点这个新的内存。所以,它真的看起来更像这个引擎盖下的:

String str1 = "hello";
String str2 = str1 + " world!";
str1 = str2;

因此这就意味着若做repitively尤其是递归这种“复制粘贴+在内存中移动的东西”的过程可以是非常昂贵的。

当你在无须在做的事情和过度使用的StringBuilder的这种情况。它是可变的,并且可以附加字符串到当前一个的端部,因为它是由后面的[生长阵列(不是100%,如果这是实际的数据结构中,可以是一个列表)。

API:

  

字符的一个线程安全的可变序列。一个字符串缓冲区是像字符串,而是可以被修改。在任何时间点上,包含的字符的一些特定序列,但该序列的长度和内容可以通过某些方法调用来改变。

一个的StringBuffer被用来创建从许多字符串,例如一个字符串当要追加字符串的部件在一个循环。

当你只有一个线程访问的StringBuffer,因为StringBuilder的不同步,因而速度更快,您应该使用StringBuilder,而不是一个StringBuffer的。

AFAIK有在Java字符串大小作为语言没有上限,但可能的JVM有一个上限。

我找到了 Reggie Hutcherso 比较 String 与 StringBuffer 性能的有趣答案来源: http://www.javaworld.com/javaworld/jw-03-2000/jw-0324-javaperf.html

Java提供了StringBuffer和String类,String类用于操作不可改变的字符串。简单地说,String 类型的对象是只读且不可变的。StringBuffer类用于表示可以修改的字符。

这两个类之间的显着性能差异是,在执行简单连接时,StringBuffer 比 String 更快。在字符串操作代码中,字符串通常被连接起来。使用 String 类,连接通常按如下方式执行:

 String str = new String ("Stanford  ");
 str += "Lost!!";

如果要使用 StringBuffer 执行相同的串联,则需要如下所示的代码:

 StringBuffer str = new StringBuffer ("Stanford ");
 str.append("Lost!!");

开发人员通常认为上面的第一个示例更有效,因为他们认为使用append方法进行连接的第二个示例比使用+运算符连接两个String对象的第一个示例的成本更高。

+ 运算符看起来很无辜,但生成的代码却产生了一些惊喜。使用 StringBuffer 进行串联实际上可以生成比使用 String 快得多的代码。为了找出为什么会出现这种情况,我们必须检查两个示例生成的字节码。使用 String 的示例的字节码如下所示:

0 new #7 <Class java.lang.String>
3 dup 
4 ldc #2 <String "Stanford ">
6 invokespecial #12 <Method java.lang.String(java.lang.String)>
9 astore_1
10 new #8 <Class java.lang.StringBuffer>
13 dup
14 aload_1
15 invokestatic #23 <Method java.lang.String valueOf(java.lang.Object)>
18 invokespecial #13 <Method java.lang.StringBuffer(java.lang.String)>
21 ldc #1 <String "Lost!!">
23 invokevirtual #15 <Method java.lang.StringBuffer append(java.lang.String)>
26 invokevirtual #22 <Method java.lang.String toString()>
29 astore_1

第一行代码执行位置0到9的字节码,即:

 String str = new String("Stanford ");

然后,执行位置 10 到 29 处的字节码以进行串联:

 str += "Lost!!";

这里事情变得有趣了。为连接生成的字节码创建一个 StringBuffer 对象,然后调用其追加方法:临时 StringBuffer 对象在位置 10 创建,并在位置 23 调用其追加方法。由于 String 类是不可变的,因此必须使用 StringBuffer 进行串联。

对 StringBuffer 对象执行串联后,必须将其转换回 String。这是通过调用位置 26 处的 toString 方法来完成的。此方法从临时 StringBuffer 对象创建一个新的 String 对象。创建这个临时 StringBuffer 对象以及随后将其转换回 String 对象的成本非常高。

总之,上面的两行代码创建了三个对象:

  1. 位置 0 处的 String 对象
  2. 位置 10 处的 StringBuffer 对象
  3. 位置 26 处的 String 对象

现在,让我们看一下使用 StringBuffer 为示例生成的字节码:

0 new #8 <Class java.lang.StringBuffer>
3 dup
4 ldc #2 <String "Stanford ">
6 invokespecial #13 <Method java.lang.StringBuffer(java.lang.String)>
9 astore_1
10 aload_1 
11 ldc #1 <String "Lost!!">
13 invokevirtual #15 <Method java.lang.StringBuffer append(java.lang.String)>
16 pop

第一行代码执行位置 0 到 9 的字节码:

 StringBuffer str = new StringBuffer("Stanford ");

然后执行位置 10 到 16 处的字节码以进行串联:

 str.append("Lost!!");

请注意,与第一个示例中的情况一样,此代码调用 StringBuffer 对象的append 方法。然而,与第一个示例不同的是,不需要创建临时 StringBuffer 然后将其转换为 String 对象。此代码仅在位置 0 处创建一个对象,即 StringBuffer。

总之,StringBuffer 串联比 String 串联要快得多。显然,如果可能的话,应该在此类操作中使用 StringBuffer。如果需要 String 类的功能,请考虑使用 StringBuffer 进行串联,然后执行一次到 String 的转换。

通过打印字符串的哈希码/ StringBuffer对象之后的任何附加操作还证明,字符串对象是越来越内部用新值每次重新创建,而不是使用相同的字符串对象。

public class MutableImmutable {

/**
 * @param args
 */
public static void main(String[] args) {
    System.out.println("String is immutable");
    String s = "test";
    System.out.println(s+"::"+s.hashCode());
    for (int i = 0; i < 10; i++) {
        s += "tre";
        System.out.println(s+"::"+s.hashCode());
    }

    System.out.println("String Buffer is mutable");

    StringBuffer strBuf = new StringBuffer("test");
    System.out.println(strBuf+"::"+strBuf.hashCode());
    for (int i = 0; i < 10; i++) {
        strBuf.append("tre");
        System.out.println(strBuf+"::"+strBuf.hashCode());
    }

 }

}

输出: 它与它的哈希码沿打印对象值

    String is immutable
    test::3556498
    testtre::-1422435371
    testtretre::-1624680014
    testtretretre::-855723339
    testtretretretre::2071992018
    testtretretretretre::-555654763
    testtretretretretretre::-706970638
    testtretretretretretretre::1157458037
    testtretretretretretretretre::1835043090
    testtretretretretretretretretre::1425065813
    testtretretretretretretretretretre::-1615970766
    String Buffer is mutable
    test::28117098
    testtre::28117098
    testtretre::28117098
    testtretretre::28117098
    testtretretretre::28117098
    testtretretretretre::28117098
    testtretretretretretre::28117098
    testtretretretretretretre::28117098
    testtretretretretretretretre::28117098
    testtretretretretretretretretre::28117098
    testtretretretretretretretretretre::28117098

一个StringBuffer或其年轻的和更快的弟弟 StringBuilder 是首选,只要你会做的味道了很多的字符串连接的

string += newString;

或等价

string = string + newString;

因为上述构建体中隐式地创建串每次这将是一个巨大的性能和降低。甲StringBuffer / StringBuilder是罩下最好是具有动态膨胀List<Character>比较。

A String 是一个不可变的字符数组。

A StringBuffer 是一个可变字符数组。经常转换回 String 当完成变异时。

由于两者都是数组,因此两者的最大大小都等于整数的最大大小,即 2^31-1(请参阅 Java文档, ,还请查看两者的 JavaDoc StringStringBuffer)。这是因为 .length 数组的参数是原语 int. 。(看 数组).

字符串是不可改变的,也就是说,当你在一个字符串你真的创建了一个全新的字符串进行操作。

的StringBuffer 是可变的,并且你可以附加到它,以及其长度重置为0。

在实践中,编译器似乎期间字符串连接到用StringBuffer出于性能的原因

String is immutable. 

为什么?查看 这里.

StringBuffer is not. It is thread safe. 

进一步的问题,例如何时使用哪些概念和其他概念,可以在下面找到 .

希望这可以帮助。

虽然我知道这不是主要的区别因素,但今天我注意到 StringBuffer(和 StringBuilder)提供了一些 String 没有的有趣方法。

  • 撤销()
  • setCharAt()

差异是

  1. 只有在 细绳 班级 + 运算符超载。我们可以使用以下方法连接两个 String 对象 + 运算符,但在以下情况下 字符串缓冲区 我们不能。
  2. 细绳 类重写了 toString(), equals(), hashCode() 的 目的 类,但是 字符串缓冲区 仅覆盖 toString()。

    String s1 = new String("abc");
    String s2 = new String("abc");
    System.out.println(s1.equals(s2));  // output true
    
    StringBuffer sb1 = new StringBuffer("abc");
    StringBuffer sb2 = new StringBuffer("abc");
    System.out.println(sb1.equals(sb2));  // output false
    
  3. 细绳 类是两者 可串行化可比, , 但 字符串缓冲区 只是 可串行化.

    Set<StringBuffer> set = new TreeSet<StringBuffer>();
    set.add(sb1);
    set.add(sb2);
    System.out.println(set);  // gives ClassCastException because there is no Comparison mechanism
    
  4. 我们可以创建一个带有或不带有的 String 对象 新的 运算符,但 StringBuffer 对象只能使用创建 新的 操作员。

  5. String 是不可变的,但 StringBuffer 是可变的。
  6. StringBuffer 是同步的,而 String 不是。
  7. StringBuffer 有一个内置的 撤销() 方法,但 String 没有。

性能方面 StringBuffer 比 String 好得多;因为每当您在 String 对象上应用串联时,就会在每个串联上创建新的 String 对象。

主要规则: String 是不可变的(不可修改)而 StringBuffer 是可变的(可修改)

这是程序化实验,您可以在其中获得性能差异

public class Test {

  public static int LOOP_ITERATION= 100000;

  public static void stringTest(){
    long startTime = System.currentTimeMillis();
    String string = "This";
    for(int i=0;i<LOOP_ITERATION;i++){
        string = string+"Yasir";
    }

    long endTime = System.currentTimeMillis();
    System.out.println(endTime - startTime);    
  }

  public static void stringBufferTest(){
    long startTime = System.currentTimeMillis();
    StringBuffer stringBuffer = new StringBuffer("This");
    for(int i=0;i<LOOP_ITERATION;i++){
        stringBuffer.append("Yasir");
    }

    long endTime = System.currentTimeMillis();
    System.out.println(endTime - startTime);
  }

  public static void main(String []args){
    stringTest()
    stringBufferTest(); 
  }
 }

字符串的输出在我的机器中 14800

StringBuffer 的输出在我的机器中 14

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top