我的代码如下:
String s = "";
for (My my : myList) {
s += my.getX();
}
当我这样做时,Findbugs总是会报错。
答案 0 :(得分:22)
如果您手动连接,我会使用+
,
String word = "Hello";
word += " World!";
但是,如果您正在迭代和连接,我建议StringBuilder
,
StringBuilder sb = new StringBuilder();
for (My my : myList) {
sb.append(my.getX());
}
答案 1 :(得分:8)
String对象在Java中是不可变的。每个+表示另一个对象。您可以使用StringBuffer来最小化创建的对象的数量。
答案 2 :(得分:4)
每次执行string+=string
时,都会调用以下方法:
private String(String s1, String s2) {
if (s1 == null) {
s1 = "null";
}
if (s2 == null) {
s2 = "null";
}
count = s1.count + s2.count;
value = new char[count];
offset = 0;
System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
}
对于StringBuilder,它来到:
final void append0(String string) {
if (string == null) {
appendNull();
return;
}
int adding = string.length();
int newSize = count + adding;
if (newSize > value.length) {
enlargeBuffer(newSize);
}
string.getChars(0, adding, value, count);
count = newSize;
}
正如您可以清楚地得出的结论,string + string
会产生很多开销,我认为如果可能的话应该避免。如果您认为使用StringBuilder很笨或很长,您可以制作一个方法并间接使用它,例如:
public static String scat(String... vargs) {
StringBuilder sb = new StringBuilder();
for (String str : vargs)
sb.append(str);
return sb.toString();
}
并使用它:
String abcd = scat("a","b","c","d");
在C#中我告诉它与string.Concat();
一样。在你的情况下,为scat编写重载是明智的,例如:
public static String scat(Collection<?> vargs) {
StringBuilder sb = new StringBuilder();
for (Object str : vargs)
sb.append(str);
return sb.toString();
}
然后你可以用:
来调用它result = scat(myList)
答案 3 :(得分:3)
编译器可以优化某些内容,例如
“富” + “酒吧”
要
StringBuilder s1 = new StringBuilder(); 。s1.append( “foo” 的)附加( “条”);
然而,这仍然不是最理想的,因为它以默认大小16开始。尽管你应该找到最大的瓶颈,然后沿着列表工作。尽管如此,特别是如果你能够计算出最佳的初始化大小,那么使用SB模式的习惯并没有什么坏处。
答案 4 :(得分:3)
过早优化可能很糟糕,并且通常会降低可读性,而且通常是完全没必要的。如果它更具可读性,请使用+
,除非您确实有一个重要的问题。
答案 5 :(得分:3)
使用“+”并不总是“坏”。在任何地方使用StringBuffer都会使代码变得非常笨重。
如果有人在密集,时间关键的循环中放了很多“+”,我会生气。如果有人在很少使用的代码中添加了很多“+”,我就不在乎了。
答案 6 :(得分:1)
我想在下面说使用plus:
String c = "a" + "b"
并在其他地方使用StringBuilder类。 正如在第一种情况中已经提到的,它将由编译器进行优化,并且更具可读性。
答案 7 :(得分:1)
FindBugs应该争论使用连接运算符(无论是“+”还是“+ =”)的原因之一是可本地化。在您给出的示例中并不是那么明显,但在以下代码的情况下,它是:
String result = "Scanning found " + Integer.toString(numberOfViruses) + " viruses";
如果这看起来有些熟悉,则需要更改编码风格。问题是,它在英语中听起来很棒,但对翻译来说可能是一场噩梦。这只是因为你不能保证翻译后句子的顺序仍然是相同的 - 有些语言将被翻译为“1 blah blah”,有些语言被翻译为“等等等等”。在这种情况下,您应该始终使用MessageFormat.format()来构建复合句子,并且使用连接运算符显然是国际化错误。
顺便说一句。我在这里放了另一个i18n缺陷,你能发现它吗?
答案 8 :(得分:0)
两个字符串连接的运行时间与字符串的长度成正比。如果它在循环中使用,则运行时间总是在增加。因此,如果循环中需要连接,最好使用像Anthony建议的StringBuilder
。