使用+来连接字符串总是一个坏主意

时间:2010-10-01 00:47:16

标签: java string internationalization coding-style

我的代码如下:

String s = "";
for (My my : myList) {
    s += my.getX();
}

当我这样做时,Findbugs总是会报错。

9 个答案:

答案 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