2012-03-28 34 views
2

我在一个Java的书,上面写着写着:Java的解释:为什么字符串不可改变使StringBuffer的更有效

因为String是不可改变的,使用StringBuffer是更有效的。

我知道String实例是不可变的。

我也明白StringBuffer使处理字符串比正常更高效。

但我不能制定出的东西是什么这两个概念连接,即如何做String是不可改变的帮助StringBuffer

谢谢:)

+2

不可变使字符串变慢。因此,StringBuffer成为一个更好的选择。两者之间不应该有直接的联系。 – 2012-03-28 03:25:38

+0

从2004年Java 5.0中的StringBuffer的Javadoc'从发布JDK 5开始,这个类已经补充了一个为单个线程StringBuilder设计的等价类。由于StringBuilder类支持所有相同的操作,所以通常应优先使用StringBuilder类,但速度更快,因为它不执行同步。 '如果你关心性能,不要使用StringBuffer。 – 2012-03-28 07:13:11

+1

@AmitBhargava - 不可变字符串对于某些事物而言速度较慢,但​​对其他事物则较快。例如,substring(带有可用的语义)通常比String是可变的更快,因为不需要复制字符。但我同意**整体**,不变性使字符串变慢(可能)。 – 2012-04-05 04:22:11

回答

1

但我不能解决的是连接这两个概念的东西,即如何使字符串不可变帮助StringBuffer?

它没有。我认为你只是曲解了你所引用的句子。

“因为字符串是不可变的,所以使用StringBuffer更高效。”

这是说,StringBuffer是一个相对更有效的选项(对于某些任务)。换句话说:“因为String是不可变的,所以使用StringBuffer比[为某些任务使用String]更高效。”

这并不是说StringBuffer的绝对速度比如果String不是不可变的速度快。当然,这不是我读报价的方式......也不是真实的说法。

8

因为字符串是不可改变的,操作字符串,如连接字符串,则必须创建新的String对象,因为很明显,你不能改变现有的String对象的状态。而用一个StringBuffer或StringBuilder的,您可以创建一个对象和简单地改变其状态。例如,如果您在for循环中执行一些主要的字符串连接,则此对象创建可能会非常昂贵。这就是说,我在这里看到很多关于不涉及大规模连接的简单字符串串联的帖子,在这种情况下,使用StringBuffer或StringBuilder是一个过早和不必要的优化的例子。

另外请注意,您应该优先使用StringBuilder而不是StringBuffer,除非您的应用程序需要访问多个线程中的对象,并且不介意这会产生额外的开销。

+1

哦。这意味着:如果我想连接字符串“abc”和“def”但不使用缓冲区。在字符串池中将有:“abc”“abcd”“abcde”“abcdef”。但是如果使用缓冲区,只需要“abc”,“abcdef”,“def”。对 ? – hqt 2012-03-28 03:28:17

+0

不正确。首先,你的例子是微不足道的,并建议使用字符串是最好的方法。只需使用字符串,该池就会具有“abc”,“def”和“abcdef”。 – 2012-03-28 03:31:57

+1

@hqt - 不,只会有abc,def和abcdef。但是想象一下在一个循环中连接10个或更多的字符串 - 然后你会为每个并置获得一个新的字符串。另一方面,编译器会优化它的位置。例如,文字'“abc”+“def”'在编译时连接在一起,而不是运行时。如果你在一个语句中执行多个运行时连接,它将会创建一个StringBuilder并进行追加 - 就像你自己使用StringBuilder手动编写一样。请参阅http://stackoverflow.com/questions/1532461。 – 2012-03-28 03:36:44

2

这意味着什么,因为String是不可变的,所以最好使用StringBuffer(或StringBuilder)进行字符串操作,因为每次更改基础字符串时都不会创建新对象。

+1

哦。这意味着:如果我想连接字符串“abc”和“def”但不使用缓冲区。在字符串池中将有:“abc”“abcd”“abcde”“abcdef”。但是如果使用缓冲区,只需要“abc”,“abcdef”,“def”。对 ? – hqt 2012-03-28 03:32:52

1

所有其他职位肯定回答的问题。我想补充一点,你应该总是选择StringBuilder而不是StringBufferStringBuffer具有内置线程同步功能,这是您几乎永远不需要的大量锁定开销。 StringBuilder没有这个,因此速度更快。

其实即使你想要线程安全,这里有some very good reasons也不要用StringBuffer

0

一成不变的概念可以很容易地用这个例子来说明

String s1 = "Hello"; 
String s2 = "Hi"; 
String s3 = "Hello"; 

if (s1 == s2){ System.out.println("s1==s2");} 
if (s1 == s3){ System.out.println("s1==s3");} 

s1 = "Hi"; 

if (s1 == s2){ System.out.println("s1==s2");} 
if (s1 == s3){ System.out.println("s1==s3");} 

如果执行这段代码,你会得到 s1==s3s1==s2。这个例子解释了什么?

当您创建s1时,编译器在其字符串表中创建了一个字符串“Hello”(我记得它的确切名称)。当你创建s2时,它会创建新的对象“Hi”。现在当你创建s3时,编译器知道它的字符串表中已经有一个对象“Hello”,所以为什么不把它引用到s3中。所以s1 = s3(记忆虎钳)。同样的事情发生在你指定的值“嗨”到S1,编译器可以看到,“喜”已经在内存中指向的S3,所以它指出它S1为好。

在StringBuffer的情况下,编译器将内存分配给对象,您可以像处理字符串时那样操作“池”。

相关问题