我第一次接触到 StringBuilder
,很惊讶因为 Java 已经有一个非常强大的String
类可以进行追加了。
为什么还需要一个新的String
类呢?
我应该去哪里学习更多关于StringBuilder
的内容呢?
我第一次接触到 StringBuilder
,很惊讶因为 Java 已经有一个非常强大的String
类可以进行追加了。
为什么还需要一个新的String
类呢?
我应该去哪里学习更多关于StringBuilder
的内容呢?
String
不允许追加。在 String
上调用每个方法都会创建一个新对象并返回它。这是因为 String
是不可变的 - 它无法改变其内部状态。
另一方面,StringBuilder
是可变的。当您调用 append(..)
时,它会更改内部 char 数组,而不是创建一个新的字符串对象。
因此,最好使用:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 500; i ++) {
sb.append(i);
}
可以使用 str.join()
方法代替 str += i
,这样可以避免创建500个新的字符串对象。
请注意,在示例中我使用了循环。正如Helios在评论中指出的那样,编译器会自动将类似于 String d = a + b + c
的表达式转换为类似于以下的内容。
String d = new StringBuilder(a).append(b).append(c).toString();
还要注意,除了 StringBuilder
之外,还有一个 StringBuffer
。区别在于前者具有同步的方法。如果您将其用作局部变量,请使用 StringBuilder
。如果可能会被多个线程访问,则使用 StringBuffer
(这种情况比较少见)。
toLowerCase
无法改变它所调用的当前字符串。因此,它会从当前字符串创建一个新的字符串。 - Bondolin以下是一个具体示例,说明为什么 -
int total = 50000;
String s = "";
for (int i = 0; i < total; i++) { s += String.valueOf(i); }
// 4828ms
StringBuilder sb = new StringBuilder();
for (int i = 0; i < total; i++) { sb.append(String.valueOf(i)); }
// 4ms
可以看到性能的差异很大。
s = sb.ToString();
的时间,以便两个示例都执行了相同的操作(结果是一个 string
)。 - Scott WhitlockString类是不可变的,而StringBuilder是可变的。
String s = "Hello";
s = s + "World";
上面的代码会创建两个对象,因为字符串是不可变的。StringBuilder sb = new StringBuilder("Hello");
sb.append("World");
上述代码只会创建一个对象,因为StringBuilder不是不可变的。
教训:每当需要多次操作/更新/追加字符串时,请使用StringBuilder,因为与String相比,它更有效率。
StringBuilder是用于构建字符串的。特别是以一种非常高效的方式构建它们。String类适用于许多事情,但实际上在将新字符串组合成较小的字符串部分时,它的性能非常差,因为每个新字符串都是一个全新的、重新分配的字符串。(它是不可变的) StringBuilder保持相同的序列并修改它(可变)。
StringBuilder类是可变的,与String不同的是,它允许您修改字符串的内容而无需创建更多的String对象,当您需要大量修改字符串时,这可以提高性能。还有一个StringBuilder的对应物叫做StringBuffer,它也是同步的,因此非常适合多线程环境。
String的最大问题在于,任何与它相关的操作都会返回一个新的对象,例如:
String s1 = "something";
String s2 = "else";
String s3 = s1 + s2; // this is creating a new object.
效率。
每次连接字符串时,都会创建一个新的字符串。例如:
String out = "a" + "b" + "c";
out
。StringBuilder
允许您就地添加字符串,根据需要调整输出字符串的大小。Java有String、StringBuffer和StringBuilder:
String:它是不可变的
StringBuffer:它是可变的且线程安全的
StringBuilder:它是可变的但不是线程安全的,自Java 1.5引入
例如String:
public class T1 {
public static void main(String[] args){
String s = "Hello";
for (int i=0;i<10;i++) {
s = s+"a";
System.out.println(s);
}
}
}
}
输出:将创建10个不同的字符串,而不仅仅是1个字符串。
Helloa
Helloaa
Helloaaa
Helloaaaa
Helloaaaaa
Helloaaaaaa
Helloaaaaaaa
Helloaaaaaaaa
Helloaaaaaaaaa
Helloaaaaaaaaaa
StringBuilder 示例:只会创建一个 StringBuilder 对象。
public class T1 {
public static void main(String[] args){
StringBuilder s = new StringBuilder("Hello");
for (int i=0;i<10;i++) {
s.append("a");
System.out.println(s);
}
}
}
StringBuilder
在追加字符串时比String
快上百倍。这里有一篇文章,附带了一个可以运行的Java脚本,你可以自己试一下:https://blog.terresquall.com/2023/08/try-it-yourself-compare-performance-java-string-stringbuilder-stringbuffer/ - John Doe