Всегда ли плохая идея использовать + для объединения строк - PullRequest
14 голосов
/ 01 октября 2010

У меня есть следующий код:

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

Findbugs всегда сообщает об ошибке, когда я делаю это.

Ответы [ 9 ]

23 голосов
/ 01 октября 2010

Я бы использовал +, если вы объединяете вручную,

String word = "Hello";
word += " World!";

Однако, если вы выполняете итерацию и объединение, я бы предложил StringBuilder,

StringBuilder sb = new StringBuilder();
for (My my : myList) {
    sb.append(my.getX());
}
9 голосов
/ 01 октября 2010

Объект String является неизменным в Java.Каждый + означает другой объект.Вы можете использовать StringBuffer, чтобы минимизировать количество создаваемых объектов.

4 голосов
/ 01 октября 2010

Каждый раз, когда вы делаете 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 # I 'м сказал примерно так же, как 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 голосов
/ 01 октября 2010

Не всегда «плохо» использовать «+». Повсеместное использование StringBuffer может сделать код действительно громоздким.

Если кто-то поместит много «+» в середине интенсивного, критичного ко времени цикла, я буду раздражен. Если бы кто-то поместил много «+» в редко используемый фрагмент кода, мне было бы все равно.

3 голосов
/ 01 октября 2010

Преждевременная оптимизация может быть плохой, так как она часто снижает читабельность и обычно совершенно не нужна. Используйте +, если он более читабелен, если только у вас нет основной проблемы.

3 голосов
/ 01 октября 2010

Компилятор может оптимизировать некоторые вещи, такие как

"Foo" + "бар"

К

StringBuilder s1 = new StringBuilder (); . S1.append ( "Foo") добавить ( "бар");

Однако это все еще неоптимально, поскольку он начинается с размера по умолчанию, равного 16. Как и во многих других вещах, вы должны найти самые большие бутылочные горлышки и пройтись по списку. Впрочем, не мешает использовать шаблон SB с самого начала, особенно если вы можете рассчитать оптимальный размер инициализации.

1 голос
/ 01 октября 2010

Одной из причин, почему FindBugs должен спорить об использовании оператора конкатенации (будь то "+" или "+ ="), является локализуемость.В приведенном вами примере это не так очевидно, но в случае следующего кода это:

String result = "Scanning found " + Integer.toString(numberOfViruses) + " viruses";

Если это выглядит несколько знакомым, вам нужно изменить свой стиль кодирования.Проблема в том, что на английском это будет звучать великолепно, но для переводчиков это может быть кошмаром.Это просто потому, что вы не можете гарантировать, что порядок перевода после перевода будет прежним - некоторые языки будут переведены как «1 бла-бла», некоторые - «бла-бла 3».В таких случаях вы всегда должны использовать MessageFormat.format () для построения составных предложений, а использование оператора конкатенации явно является ошибкой интернационализации.

Кстати.Я поставил здесь другой дефект i18n, не могли бы вы его обнаружить?

1 голос
/ 01 октября 2010

Я бы сказал, используйте плюс в следующем:

String c = "a" + "b"

И используйте класс StringBuilder везде.Как уже упоминалось в первом случае, он будет оптимизирован компилятором и станет более читабельным.

0 голосов
/ 06 марта 2018

Время работы конкатенации двух строк пропорционально длине строк. Если он используется в цикле, время работы всегда увеличивается. Поэтому, если в цикле необходима конкатенация, лучше использовать StringBuilder, как предложил Энтони.

...