请告诉我一个实时的情况来比较String
,StringBuffer
和StringBuilder
?String,StringBuffer和StringBuilder
回答
可变性差异:
String
是不变,如果你试图改变他们的价值观,另一对象被创建,而StringBuffer
和StringBuilder
是可变,使他们能够改变自己的价值观。
线程安全的区别:
的差异和StringBuilder
之间StringBuffer
是StringBuffer
是线程安全的。因此,当应用程序需要在单个线程中运行时,最好使用StringBuilder
。 StringBuilder
比StringBuffer
更有效。
情况:
- 如果字符串是不会改变的使用String类,因为
String
对象是不可改变的。 - 如果您的字符串可以更改(例如:字符串构造中的大量逻辑和操作),并且只能从单个线程访问,使用
StringBuilder
就足够了。 - 如果您的字符串可以更改,并且将从多个线程访问,请使用
StringBuffer
,因为StringBuffer
是同步的,所以您具有线程安全性。
你的意思是为了连接?
真实世界的例子:你想创建一个新的字符串出其他。
例如发送消息:
字符串
String s = "Dear " + user.name + "<br>" +
" I saw your profile and got interested in you.<br>" +
" I'm " + user.age + "yrs. old too"
的StringBuilder
String s = new StringBuilder().append.("Dear ").append(user.name).append("<br>")
.append(" I saw your profile and got interested in you.<br>")
.append(" I'm ").append(user.age).append("yrs. old too")
.toString()
或者
String s = new StringBuilder(100).appe..... etc. ...
// The difference is a size of 100 will be allocated upfront as fuzzy lollipop points out.
的StringBuffer(语法是完全一样与StringBuilder的,第E对不同)
关于
StringBuffer
与StringBuilder
前者synchonized,后来是没有的。
所以,如果你调用它几次在一个单独的线程(这是90%的情况下),StringBuilder
将运行多更快,因为它不会停止,看它是否拥有线程锁。
所以,这是推荐使用StringBuilder
(当然,除非你有一个以上的线程访问它在同一时间,这是罕见的)(使用+运算符)
String
级联可能由编译器进行优化以便在底下使用StringBuilder
,因此,它不再是值得担心的事情,在Java的前几天,这是大家所说的应该不惜一切代价避免的事情,因为每个连接都会创建一个新的String对象。现代编译器不再这样做了,但仍然使用StringBuilder
是一种好习惯,以防万一您使用“旧”编译器。
编辑
只是为了谁是好奇,这是编译器做什么该类:
class StringConcatenation {
int x;
String literal = "Value is" + x;
String builder = new StringBuilder().append("Value is").append(x).toString();
}
的javap -c StringConcatenation
Compiled from "StringConcatenation.java"
class StringConcatenation extends java.lang.Object{
int x;
java.lang.String literal;
java.lang.String builder;
StringConcatenation();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: new #2; //class java/lang/StringBuilder
8: dup
9: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
12: ldC#4; //String Value is
14: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: aload_0
18: getfield #6; //Field x:I
21: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
24: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
27: putfield #9; //Field literal:Ljava/lang/String;
30: aload_0
31: new #2; //class java/lang/StringBuilder
34: dup
35: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
38: ldC#4; //String Value is
40: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
43: aload_0
44: getfield #6; //Field x:I
47: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
50: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
53: putfield #10; //Field builder:Ljava/lang/String;
56: return
}
线编号为5 - 27用于名为“文字”的字符串
行号为31-53的字符串为名为“builder”的字符串
Ther的没有区别,正好相同代码对两个字符串都执行。
这是一个非常糟糕的例子。使用“Dear”初始化StringBuilder意味着第一个.append()将导致重新分配和复制。完全否定任何您试图通过“正常”串联获得的效率。一个更好的例子是用一个初始大小来创建它,它将保存最终字符串的全部内容。 – 2010-06-04 03:48:30
在分配的右侧使用StringBuilder来执行字符串连接通常不是一个好习惯。正如你所说,任何好的实现都会在幕后使用一个StringBuilder。此外,你的''a“+”b“的例子会被编译成一个单一的字面值'”ab“',但是如果你使用了'StringBuilder',则会导致对append()的两次不必要的调用。 – 2010-06-04 04:18:27
@Mark我不是故意使用'“a”+“b”'而是说什么是*字符串连接*关于我将其更改为显式。你不说的是,为什么不是一个好的做法。这正是现代编译器所做的。 @fuzzy,我同意,特别是当你知道最终字符串的大小是多少时(aprox)。 – OscarRyz 2010-06-04 16:40:18
另外,StringBuffer
是线程安全的,其中StringBuilder
不是。
因此,在不同的线程访问它的实时情况下,StringBuilder
可能有不确定的结果。
- 当不可变的结构适当时,您使用
String
;从String
获取新的字符序列可能在CPU时间或内存中获得不可接受的性能损失(因为数据未被复制而获得子串的CPU效率,但这意味着可能保持分配更大量的数据)。 - 当您需要创建可变字符序列时,通常使用
StringBuilder
来连接多个字符序列。 - 在与使用
StringBuilder
相同的情况下使用StringBuffer
,但是当对基础字符串的更改必须同步时(因为多个线程正在读/修改字符串缓冲区)。
查看示例here。
+1,简明的答案。 – Dolph 2010-06-04 04:11:58
简洁但不完整,它忽略了使用StringBuilder/Buffer的根本原因,即减少或消除了常规字符串串联行为的重新分配和阵列副本。 – 2010-06-04 04:21:39
“你在处理不可变字符串时使用字符串” - 没有任何意义。字符串的实例是不可变的,所以也许该注释应该是“当由于不变性导致的内存使用不重要时使用字符串”。被接受的答案涵盖了它很好的基础。 – fooMonster 2011-08-03 14:24:41
基础:
String
是不可变的类,它不能被改变。 StringBuilder
是可以附加到,替换的字符或删除,并最终转化为String
StringBuffer
一个可变类是StringBuilder
原来的同步版本你应该在你只有一个线程访问所有的情况下宁愿StringBuilder
你的对象。
的详细信息:
还要注意的是StringBuilder/Buffers
不是魔法,他们只是使用数组作为后备对象和数组必须被重新分配时,以往任何时候都得到充分。请确保并创建您的StringBuilder/Buffer
对象,这些对象最初足够大,在每次调用.append()
时都不需要不断调整其大小。
重新调整大小会变得非常堕落。每次需要扩展时,它基本上都会将后端阵列重新调整为当前大小的2倍。这可能会导致大量RAM分配,并且StringBuilder/Buffer
类开始变大时不会使用。
在Java中String x = "A" + "B";
在幕后使用StringBuilder
。因此,对于简单的情况,宣布您自己没有任何好处。但是,如果您正在构建String
较大的对象,比如小于4k,那么声明StringBuilder sb = StringBuilder(4096);
比串联或使用只有16个字符的default constructor效率更高。如果您的String
将小于10k,则使用构造函数将其初始化为10k以确保安全。但是如果它初始化为10k,那么你写了1个字符超过10k,它将被重新分配并复制到一个20k数组。所以初始化高于低于。
在自动重新调整大小写的情况下,在第17个字符处,支持数组被重新分配并复制到32个字符,在第33个字符处,会再次发生,您将重新分配并将该数组复制为64个字符。你可以看到如何退化到批次的重新分配和副本,这是你真的试图避免使用StringBuilder/Buffer
摆在首位。
这是从JDK 6源代码AbstractStringBuilder
void expandCapacity(int minimumCapacity) {
int newCapacity = (value.length + 1) * 2;
if (newCapacity < 0) {
newCapacity = Integer.MAX_VALUE;
} else if (minimumCapacity > newCapacity) {
newCapacity = minimumCapacity;
}
value = Arrays.copyOf(value, newCapacity);
}
最佳做法是初始化StringBuilder/Buffer
有点大于你认为你会需要,如果你不知道正确的断手String
将会有多大,但你可以猜到。比你需要的内存稍多的分配会比大量的重新分配和拷贝更好。
还要小心使用String
初始化StringBuilder/Buffer
,因为它只会分配String + 16个字符的大小,在大多数情况下,这只会启动您试图避免的简并重新分配和复制循环。以下内容直接来自Java 6源代码。
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
如果你偶然做与StringBuilder/Buffer
一个实例,你没有创建和无法控制被称为构造函数结束,还有就是避免退化的方式重新分配并复制行为。请拨打.ensureCapacity()
,以确保您的结果String
适合。
替代方案:
正如一个音符,如果你正在做真正重String
建设和操作,还有一个更注重性能的替代称为Ropes。
另一种替代方法,是创建一个StringList
实行由子类ArrayList<String>
,并添加计数器来跟踪的字符上的列表中的每一个.append()
和其它突变操作的数量,然后覆盖.toString()
创建的确切大小的StringBuilder
您需要并遍历列表并构建输出,甚至可以将StringBuilder
作为实例变量,并“缓存”.toString()
的结果,并且只有在某些更改时才需要重新生成结果。
当构建固定格式化输出时,也请不要忘记String.format()
,编译器可以优化它们,因为它们使其更好。
'String x =“A”+“B”;'真的编译成StringBuilder吗?为什么它不能编译为'String x =“AB”;',如果在编译时不知道组件,它应该只使用一个StringBuilder。 – 2010-06-04 03:58:43
它可能会优化字符串常量,我不记得从上次反编译字节码,但我知道如果在那里有任何变量,它肯定会使用StringBuilder实现。您可以下载JDK源代码并找出自己。 “A”+“B”确实是一个人为的例子。 – 2010-06-04 04:06:35
我在想String.format()。我从未真正看到它在项目中使用。通常是StringBuilder。那么,通常它实际上是“A”+“B”+“C”,因为人们懒惰;)我倾向于总是使用StringBuilder,即使它只有两个字符串被连接起来,因为将来可能会追加更多的字符串。我从来没有使用String.format(),主要是因为我从来不记得它引入了什么JDK - 我看到它是JDK1.5,我会用它来支持其他选项。 – jamiebarrow 2010-10-08 10:37:45
请注意,如果您使用Java 5或更新版本,则应使用StringBuilder
而不是StringBuffer
。从API文档:
从发布JDK 5开始,此类已添加了一个旨在供单个线程
StringBuilder
使用的等效类。StringBuilder
类通常应优先于此类使用,因为它支持所有相同的操作,但速度更快,因为它不执行同步。
实际上,你几乎从不会同时在多个线程中使用它,所以StringBuffer
所做的同步几乎总是不必要的开销。
个人而言,我不认为StringBuffer
有任何真实世界的用途。我何时想通过操纵字符序列来在多个线程之间进行通信?这听起来没有用处,但也许我还没有看到光:)
在java中,字符串是不可变的。作为不可变的,我们的意思是一旦创建了一个字符串,我们就不能改变它的值。 StringBuffer是可变的。一旦创建了一个StringBuffer对象,我们只需将内容追加到对象的值而不是创建一个新对象。 StringBuilder与StringBuffer类似,但它不是线程安全的。 StingBuilder的方法不同步,但与其他字符串相比,Stringbuilder运行速度最快。 您可以通过实施它们来了解String, StringBuilder and StringBuffer之间的区别。
String和其他两个类的区别在于String是不可变的,另外两个是可变类。
但是为什么我们有两个类为同一目的?
原因是StringBuffer
是线程安全的,StringBuilder
不是。 StringBuilder
是StringBuffer Api
一个新的类,它是在JDK5
介绍,并始终建议,如果你是在单线程环境中工作,因为它是多Faster
---------------------------------------------------------------------------------- String StringBuffer StringBuilder ---------------------------------------------------------------------------------- Storage Area | Constant String Pool Heap Heap Modifiable | No (immutable) Yes(mutable) Yes(mutable) Thread Safe | Yes Yes No Performance | Fast Very slow Fast ----------------------------------------------------------------------------------
字符串
String class
表示字符串。 Java程序中的所有字符串文字(例如)均作为此类的实例实现。
字符串对象是不可变一旦它们被创建,我们不能改变。 (字符串是常数)
如果使用构造或方法然后这些字符串将被存储在堆内存以及
SringConstantPool
创建一个字符串。但在保存到池中之前,它调用intern()
方法使用equals方法检查池中的相同内容的对象可用性。 如果字符串复制在池中可用,则返回参考。否则,将String对象添加到池中并返回引用。- Java语言提供对字符串连接符(
+
)特别支持,以及对其他对象的字符串转换。字符串连接通过StringBuilder(或StringBuffer)类及其append方法实现。
String heapSCP = new String("Yash"); heapSCP.concat("."); heapSCP = heapSCP + "M"; heapSCP = heapSCP + 777; // For Example: String Source Code public String concat(String str) { int otherLen = str.length(); if (otherLen == 0) { return this; } int len = value.length; char buf[] = Arrays.copyOf(value, len + otherLen); str.getChars(buf, len); return new String(buf, true); }
- Java语言提供对字符串连接符(
字符串文本被存储在
StringConstantPool
。String onlyPool = "Yash";
StringBuilderStringBuffer和是字符可变的序列。这意味着可以改变这些对象的值。 StringBuffer与StringBuilder具有相同的方法,但StringBuffer中的每个方法都是同步的,因此它是线程安全的。
只能使用new运算符创建StringBuffer和StringBuilder数据。所以,他们被存储在堆内存中。
StringBuilder的实例对多线程不安全。如果需要这种同步,那么建议使用StringBuffer。
StringBuffer threadSafe = new StringBuffer("Yash"); threadSafe.append(".M"); threadSafe.toString(); StringBuilder nonSync = new StringBuilder("Yash"); nonSync.append(".M"); nonSync.toString();
的StringBuffer和StringBuilder的是具有特殊方法喜欢。,
replace(int start, int end, String str)
和reverse()
。注意:StringBuffer的和SringBuilder是可变的,因为他们提供的
Appendable Interface
实施。
当要使用哪一个。
如果你不打算每次都改变数值,那么最好使用
String Class
。作为泛型的一部分,如果您想对Comparable<T>
进行排序或比较某个值,则可以使用String Class
。//ClassCastException: java.lang.StringBuffer cannot be cast to java.lang.Comparable Set<StringBuffer> set = new TreeSet<StringBuffer>(); set.add(threadSafe); System.out.println("Set : "+ set);
如果你想每次随时随地的StringBuilder比StringBuffer的更快修改数值。如果多个线程正在修改StringBuffer的值。
- 1. StringBuffer vs StringBuilder
- 2. StringBuffer vs StringBuilder VS StringTokenizer
- 3. java String和StringBuilder
- 4. StringBuilder和Stringbuffer有什么区别?
- 5. 测试StringBuilder和StringBuffer之间的区别
- 6. Stringbuffer,Stringbuilder何时使用?
- 7. StringBuilder VS StringBuffer OR vector Vs ArrayList
- 8. JAVA String vs StringBuffer
- 9. StringBuffer append()或String +?
- 10. 我们可以在String中添加String数组到StringBuffer或StringBuilder中吗?
- 11. String.Format vs“string”+“string”或StringBuilder?
- 12. Java String和StringBuffer如何工作
- 13. StringBuffer或StringBuilder用于我的查询
- 14. StringBuilder与StringBuffer - 助记符想要
- 15. 凡用StringBuffer/StringBuilder的非字符串
- 16. Groovy的字面的StringBuilder/StringBuffer的
- 17. 的StringBuffer/StringBuilder的大小在Java
- 18. Servlet的doFilter方法中的StringBuffer或StringBuilder?
- 19. Java - 带有3种类型的有界类型的泛型方法:String,StringBuilder,StringBuffer
- 20. String vs StringBuffer。 IDEA的提示
- 21. 关于方法在StringBuffer和StringBuilder中没有被覆盖?
- 22. 为什么不让StringBuilder和StringBuffer实现一个通用接口?
- 23. 如何比较StringBuffer对象和String对象
- 24. 字符串方法Append():StringBuilder的VS StringBuffer的
- 25. 为什么新的StringBuffer(新的StringBuilder(“foo”))能够工作?
- 26. 为什么StringBuffer/StringBuilder不覆盖equals或hashCode?
- 27. 什的特殊使用StringBuilder的insted的StringBuffer的
- 28. Android SAX的XML解析器与字符串或Stringbuilder或Stringbuffer
- 29. 我应该使用StringBuilder还是StringBuffer作为webapps?
- 30. 什么时候StringBuffer/StringBuilder没有被编译器隐式使用?
此外,使用字符串进行逻辑操作相当慢,并且根本不建议,因为JVM将字符串转换为字节码中的StringBuffer。大量的开销浪费从String转换为StringBuffer,然后再次返回String。 – 2010-06-04 08:28:00
所以在'Strings'中,当我们改变值时创建另一个对象。旧的对象引用是否被取消,以至于它可能被'GC'垃圾回收,或者甚至是垃圾回收? – 2014-05-09 07:07:18
@PietervanNiekerk你对逻辑运算有什么意义? – emlai 2015-09-29 10:38:38