我是StringBuilder
第一次接触,感到惊讶,因为Java已经具有一个非常强大的String
类,可以追加。
为什么要上第二String
堂课?
在哪里可以了解更多信息StringBuilder
?
我是StringBuilder
第一次接触,感到惊讶,因为Java已经具有一个非常强大的String
类,可以追加。
为什么要上第二String
堂课?
在哪里可以了解更多信息StringBuilder
?
Answers:
String
不允许附加。您在上调用的每个方法都会String
创建一个新对象并返回它。这是因为String
它是不可变的-它无法更改其内部状态。
另一方面StringBuilder
是可变的。调用append(..)
它时,它会更改内部char数组,而不是创建一个新的字符串对象。
因此,拥有:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 500; i ++) {
sb.append(i);
}
而不是str += i
,这将创建500个新的字符串对象。
请注意,在示例中,我使用了循环。正如helios在评论中指出的那样,编译器会自动将类似的表达式转换String d = a + b + c
为
String d = new StringBuilder(a).append(b).append(c).toString();
另请注意StringBuffer
,除了StringBuilder
。区别在于前者具有同步方法。如果将其用作局部变量,请使用StringBuilder
。如果碰巧有可能被多个线程访问,请使用StringBuffer
(这种情况较为罕见)
这是一个具体的示例,说明为什么-
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
)。
效率。
每次连接字符串时,都会创建一个新字符串。例如:
String out = "a" + "b" + "c";
这将创建一个新的临时字符串,将“ a”和“ b”复制到其中以得到“ ab”。然后,它创建另一个新的临时字符串,将“ ab”和“ c”复制到其中,得到“ abc”。然后将此结果分配给out
。
结果是Schlemiel the Painter算法的O(n²)(二次)时间复杂度。
StringBuilder
另一方面,可让您就地附加字符串,并根据需要调整输出字符串的大小。
Java具有String,StringBuffer和StringBuilder:
字符串:不可变
StringBuffer:其可变和线程安全
StringBuilder:其可变但不是ThreadSafe,在Java 1.5中引入
字符串,例如:
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例如:仅将创建1个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);
}
}
}