Еще раз в строке добавить против конкат против + - PullRequest
26 голосов
/ 22 января 2012

Может быть, я расщепляю волосы, но мне было интересно в следующем случае:

String newString = a + b + c;  //case 1


String newString = a.concat(b).concat(c);   //case 2

StringBuilder newString = new StringBuilder(); //case 3
newString.append(a);
newString.append(b);    
newString.append(c);

Что лучше всего использовать?

Лучшее, что я имею в виду в в любом случае .

Читая об этом, другие посты говорят, что случай 3 не настолько оптимален с точки зрения оптимальной производительности, другие - что случай 1 закончится в случае 3 и т. Д.

Чтобы быть более конкретным.

Например, откладывая все в сторону, какой стиль больше подходит для просмотра другим программистом, если вам нужно было поддерживать его код?

Или что вы считаете более эффективным программированием?
Или вы думаете, быстрее и т. Д.

Я не знаю, как еще выразить это.

Ответ, например, например случай 3 может быть быстрее, но подавляющее большинство программистов предпочитают случай 1, потому что он наиболее читабелен, также принимается, если он хорошо проработан

Ответы [ 5 ]

22 голосов
/ 22 января 2012

Случай 1 является кратким, четко выражает намерение и эквивалентен случаю 3.

Случай 2 менее эффективен, а также менее читабелен.

Случай 3 почти так же эффективен, как случай 1, но длиннее и менее читабелен.

Использование варианта 3 лучше использовать только тогда, когда вам нужно объединить в цикле. В противном случае компилятор компилирует случай 1 в случай 3 (за исключением того, что он создает StringBuilder с new StringBuilder(a)), что делает его еще более эффективным, чем ваш случай 3).

7 голосов
/ 22 января 2012

Случай 3 - это наиболее эффективная форма, но JVM преобразует случай 1 в случай 3.

Но я считаю, что случай 2 является наихудшим, он не так удобен для чтения, как случай 1, и не так эффективен, как случай3.

Если вы хотите объединить строку в цикле, просто используйте случай 3, вы можете легко проверить выигрыш в производительности, но если он не в цикле (или вы не добавляете много строк в последовательности) они почти одинаковы.

Случаи, которые вы не должны использовать оператор +:

String a = "";
for (String x : theStrings) {
    a += x;
}

или

String a = b + c;
a = a + d;
a = a + e;
a = a + f;
2 голосов
/ 22 января 2012

Случай 3 лучше в большинстве аспектов.В случае 3 вы не будете создавать 3 строковых объекта.Из-за неизменности строки 2 будет иметь издержки на создание строкового объекта для каждого + (или) конкатата.

РЕДАКТИРОВАТЬ: перечитайте документ и согласитесь с большинством комментариев, вариант 1 - случай 3.

1 голос
/ 23 января 2012

Для простых случаев использование + явно более читабельно.

Для редких и более сложных случаев, StringBuilder имеет смысл.Если вы разделяете линии, то + может быстро привести к снижению производительности.Циклы переходят от производительности O (n) к O (n ^ 2) - не проблема, если n мала, но большая проблема, если n может быть большой в неловких условиях (возможно,когда делаете что-то критическое или когда кто-то злонамерен).

Вопреки другим ответам, если у вас есть только три строки, concat может быть победителем.Я сумасшедший?Рассмотрим два других варианта.Вы создаете объект StringBuilder с массивом.Добавление строк может также потребовать замены массива, и у вас могут остаться нечетные биты в конце массива (это определенная степень детализации для выделения, поэтому несколько дополнительных char s могут увеличивать или не увеличивать использование памяти).Вы можете вычислить необходимую емкость, если ненавидите всех, кто читает ваш код.В лучшем случае - два массива (один для StringBuilder, один для String (без совместного использования за последние восемь лет)), каждый из которых имеет размер текста результата и два других объекта (StringBuilder и String).Теперь для concat вы собираетесь выделить String объекты с двумя массивами, но первый массив будет на c.length() короче.Это победа!Ну, не для читабельности.

Отказ от ответственности: JVM может выполнять дикую оптимизацию, включая распределение стека после escape-анализа и специальный набор основных классов.Они с большей вероятностью оптимизируют обычный и простой код, чем замаскированный вручную код.

0 голосов
/ 26 сентября 2018

При анализе производительности с JDK 1.8 я нашел случай 2 в качестве победителя с точки зрения производительности.

class Solution {
public static void main(String[] args) {
   String s ="ABC", s1 = "", s2 = "", s3 = "";
   long t1 = System.nanoTime();
   for(int i = 1; i < 11; i++) {
       s1 = s1 + s;
   }
   System.out.println(System.nanoTime() - t1);
   System.out.println(s1);

   long t2 = System.nanoTime();
   for(int i = 1; i < 11; i++) {
       s2 = s2.concat(s);
   }
   System.out.println(System.nanoTime() - t2);
   System.out.println(s2);

   long t3 = System.nanoTime();
   StringBuilder sb = new StringBuilder();
   for(int i = 1; i < 11; i++) {
       sb.append(s);
   }
   s3 = sb.toString();
   System.out.println(System.nanoTime() - t3);
   System.out.println(s3);
 }
}

Результаты:

40615

ABCABCABCABCABCABCABCABCABCABC

9157

ABCABCABCABCABCABCABCABCABCABC

20243

ABCABCABCABCABCABCABCABCABCABC

...