请告诉我一个实时情况比较字符串,StringBuffer,和StringBuilder?
当前回答
In java, String is immutable. Being immutable we mean that once a String is created, we can not change its value. StringBuffer is mutable. Once a StringBuffer object is created, we just append the content to the value of object instead of creating a new object. StringBuilder is similar to StringBuffer but it is not thread-safe. Methods of StingBuilder are not synchronized but in comparison to other Strings, the Stringbuilder runs fastest. You can learn difference between String, StringBuilder and StringBuffer by implementing them.
其他回答
In java, String is immutable. Being immutable we mean that once a String is created, we can not change its value. StringBuffer is mutable. Once a StringBuffer object is created, we just append the content to the value of object instead of creating a new object. StringBuilder is similar to StringBuffer but it is not thread-safe. Methods of StingBuilder are not synchronized but in comparison to other Strings, the Stringbuilder runs fastest. You can learn difference between String, StringBuilder and StringBuffer by implementing them.
你是说为了串联吗?
真实世界的例子:您希望从许多其他字符串中创建一个新字符串。
例如,发送消息:
字符串
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()
Or
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完全相同,只是效果不同)
关于
StringBuffer vs. StringBuilder
前者是同步的,后者不是。
因此,如果在一个线程中多次调用它(90%的情况下),StringBuilder将运行得更快,因为它不会停下来查看它是否拥有线程锁。
因此,建议使用StringBuilder(当然,除非您有多个线程同时访问它,这是很少见的)
字符串连接(使用+操作符)可能会被编译器优化以在下面使用StringBuilder,因此,它不再是需要担心的事情,在Java的早期,这是每个人都说应该不惜一切代价避免的事情,因为每个连接都会创建一个新的String对象。现代编译器不再这样做了,但使用StringBuilder代替它仍然是一个很好的实践,以防您使用“旧”编译器。
edit
对于那些好奇的人来说,这是编译器为这个类做的事情:
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行的字符串名为“literal”
编号为31-53的行用于名为“builder”的字符串
没有区别,对两个字符串执行的代码完全相同。
下面是一个小代码片段,演示了如何在异步环境中破坏StringBuilder
public static void main(String[] args) throws InterruptedException {
StringBuilder builder = new StringBuilder();
ExecutorService executorService = Executors.newFixedThreadPool(50);
for (int i = 0; i < 1000 * 1000; i++) {
executorService.submit(new AppendRunnable(builder));
}
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.MINUTES);
Stream.of(builder.toString().split(System.lineSeparator()))
.filter(line -> !line.equals("I just appended this!"))
.forEach(System.out::println);
}
record AppendRunnable(StringBuilder stringBuilder) implements Runnable {
@Override
public void run() {
stringBuilder.append("I just appended this!\n");
}
}
本质上,我们将字符串附加到构建器中,并期望它们都等于“我刚刚附加了这个!”。但它们不是,其中一些前缀是空字符,因为构建器的内部字符缓冲区没有同步,它被错误地调整了大小。在这种情况下使用StringBuffer可以解决问题。更多详细信息请点击这里
---------------------------------------------------------------------------------- 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 ----------------------------------------------------------------------------------
另外,StringBuffer是线程安全的,而StringBuilder不是。
因此,在实时情况下,当不同的线程正在访问它时,StringBuilder可能会有一个不确定的结果。
推荐文章
- Java 8流和数组操作
- Java Regex捕获组
- 如何在Python中按字母顺序排序字符串中的字母
- Openssl不被视为内部或外部命令
- 如何添加自定义方法到Spring Data JPA
- 如何在Ubuntu中设置Java环境路径
- 无法执行dex:在Eclipse中超过GC开销限制
- 有人能解释一下JPA和Hibernate中的mappedBy吗?
- 是什么导致JNI调用变慢?
- Java中的&和&&有什么区别?
- 使用Java的Collections.singletonList()?
- python: SyntaxError: EOL扫描字符串文字
- PHP子字符串提取。获取第一个'/'之前的字符串或整个字符串
- Maven使用多个src目录编译
- 导入时无法解析符号