Java和StringBuffer有什么区别?
Java和StringBuffer有什么区别?
有最大的string大小?
String
用于处理不能更改的string(只读和不可变)。
StringBuffer
用于表示可以修改的字符。
性能明智, StringBuffer
执行连接时速度更快。 这是因为当你连接一个String
,你每次创build一个新的对象(内部),因为String
是不可变的。
您也可以使用类似于StringBuffer
但不同步。 其中任何一个的最大大小是Integer.MAX_VALUE
(2 31 – 1 = 2,147,483,647)或最大堆大小除以2(请参阅Javastring可以有多less个字符? )。 更多信息在这里 。
一个String
是不可变的,即当它被创build时,它永远不会改变。
当你需要一块一块地构造一个string时,使用一个StringBuffer
(或者它的非同步表兄弟StringBuilder
),而不需要在构build很多小String
的性能开销。
两者的最大长度都是Integer.MAX_VALUE,因为它们在内部存储为数组,而Java数组的长度只有伪字段的int
。
在String
和StringBuffer
之间进行多重连接的性能改进是相当重要的。 如果您运行以下testing代码,您将看到不同之处。 在我使用Java 6的古老笔记本电脑上,我得到了以下结果:
与stringConcat采取:1781ms 带有StringBuffer的Concat花费了: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是一个不可变的类。 这意味着一旦你像下面这样实例化一个string的实例:
String str1 = "hello";
内存中的对象不能被修改。 相反,你将不得不创build一个新的实例,复制旧的string并追加任何其他的例子:
String str1 = "hello"; str1 = str1 + " world!";
真正发生的事情是,我们不更新现有的str1对象…我们正在重新分配新的内存,复制“hello”数据并追加“world!”。 到最后,然后设置str1的引用来指向这个新的内存。 所以看起来更像这样:
String str1 = "hello"; String str2 = str1 + " world!"; str1 = str2;
因此,如果重复地执行这个“复制+粘贴和移动内存”过程可能是非常昂贵的。
当你处于这种不得不一遍又一遍地使用StringBuilder的情况下。 它是可变的,并且可以将string附加到当前的string的末尾,因为它是通过[增长数组]返回的(不是100%,如果这是实际的数据结构,可以是列表)。
从API:
一个线程安全的,可变的字符序列。 string缓冲区就像一个string,但可以修改。 在任何时候它都包含一些特定的字符序列,但是序列的长度和内容可以通过某些方法调用来改变。
StringBuffer用于从多个string中创build单个string,例如,当您想要在循环中追加string的部分时。
如果只有一个线程访问StringBuffer,则应使用StringBuilder而不是StringBuffer,因为StringBuilder不同步,因此速度更快。
AFAIK在Java中作为一种语言没有string大小的上限,但JVM可能有一个上限。
我发现对比较性能感兴趣的答案由Reggie Hutcherso String vs StringBuffer 来源 : http : //www.javaworld.com/javaworld/jw-03-2000/jw-0324-javaperf.html
Java提供了StringBuffer和String类,而String类用于处理不能更改的string。 简而言之,Stringtypes的对象是只读和不可变的。 StringBuffer类用于表示可以修改的字符。
这两个类之间的显着性能差异在于执行简单连接时StringBuffer比String快。 在string操作代码中,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!!";
事情在这里变得有趣。 为连接生成的字节码创build一个StringBuffer对象,然后调用它的append方法:临时StringBuffer对象在位置10处创build,其append方法在位置23处被调用。因为String类是不可变的,所以必须使用StringBuffer级联。
在StringBuffer对象上执行连接之后,必须将其转换回String。 这是通过调用位置26处的toString方法完成的。此方法从临时StringBuffer对象创build一个新的String对象。 这个临时的StringBuffer对象的创build及其后续的转换回String对象是非常昂贵的。
总之,上面的两行代码导致创build三个对象:
- 位置0的String对象
- 位置10的StringBuffer对象
- 位置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方法。 不像第一个例子,不需要创build一个临时的StringBuffer,然后把它转换成一个String对象。 此代码只在位置0处创build一个对象StringBuffer。
总之,StringBuffer的连接比String连接快得多。 显然,在可能的情况下,应该在这种types的操作中使用StringBuffers。 如果需要使用String类的function,请考虑使用StringBuffer进行连接,然后对String执行一次转换。
一个StringBuffer
或其年轻和更快的兄弟StringBuilder
是首选,当你要去做很多string连接的味道
string += newString;
或等同地
string = string + newString;
因为上面的构造每次隐含地创build一个新的string,这将是一个巨大的性能和下降。 一个StringBuffer
/ StringBuilder
最好与dynamic扩展的List<Character>
。
一个String
是一个不可变的字符数组。
一个StringBuffer
是一个可变的字符数组。 在完成变异后经常转换回String
。
由于两者都是数组,所以两者的最大值都等于一个整数的最大值,即2 ^ 31-1(参见JavaDoc ,同时检查String
和StringBuffer
的JavaDoc)。这是因为.length
一个数组的参数是一个原始的int
。 (见数组 )。
string是不可变的,这意味着当您对string执行操作时,您确实正在创build一个全新的string。
StringBuffer是可变的,你可以附加到它并将其长度重置为0。
实际上, 出于性能原因 ,编译器似乎在string连接期间使用StringBuffer。
String is immutable.
为什么? 在这里检查。
StringBuffer is not. It is thread safe.
进一步的问题,如什么时候使用哪些和其他的概念可以在这之后得出结论。
希望这可以帮助。
虽然我明白,这不是一个主要的区别因素,我今天注意到,StringBuffer(和StringBuilder)提供了一些有趣的方法,string没有。
- 相反()
- setCharAt()
通过在任何附加操作之后打印String / StringBuffer对象的哈希码也certificate,每次使用新值而不是使用相同的String对象时,内部重新创buildString对象。
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
差别是
- 只有在String类+运算符被重载。 我们可以使用+运算符连接两个String对象,但是在StringBuffer的情况下我们不能。
-
String类重写Object类的toString(),equals(),hashCode(),但StringBuffer只覆盖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
-
String类既是Serializable也是Comparable ,但StringBuffer只有Serializable 。
Set<StringBuffer> set = new TreeSet<StringBuffer>(); set.add(sb1); set.add(sb2); System.out.println(set); // gives ClassCastException because there is no Comparison mechanism
-
我们可以创build一个带有和不带有新操作符的String对象,但是StringBuffer对象只能使用新操作符来创build。
- string是不可变的,但StringBuffer是可变的。
- StringBuffer是同步的,而String不是。
- StringBuffer有一个内置的reverse()方法,但String没有它。
性能明智的StringBuffer比String好得多; 因为无论何时在String对象上应用连接,都会在每个连接上创build新的String对象。
主要规则:string是不可变的(Non Modifiable),而StringBuffer是可变的(Modifiable)
这里是您获得性能差异的程序化实验
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(); } }
string的输出在我的机器 14800
StringBuffer的输出在我的机器中 14