Использование .append (строка1 + строка 2) vs .append (строка1) .append (строка2)

Мне интересно, может ли кто-нибудь дать мне ответ, какой из этих операторов будет лучше работать в java с использованием объекта StringBuilder:

С использованием

.append(string1 + string 2) 

vs

.append(string1).append(string2)

person Kyle Thayer    schedule 19.12.2013    source источник
comment
Я бы выбрал второй вариант, так как первый, скорее всего, создаст промежуточную (ненужную) строку   -  person Алексей    schedule 19.12.2013
comment
По теме: stackoverflow.com/questions/65668/   -  person Joel    schedule 19.12.2013
comment
Если обе строки являются константами времени компиляции, используйте +; компилятор объединится во время компиляции. В противном случае используйте два добавления.   -  person Ed Staub    schedule 19.12.2013


Ответы (4)


Второй вариант почти наверняка будет лучше (при условии, что существует какая-либо заметная разница в производительности). Когда вы пишете что-то вроде

string1 + string2

это внутренне переведено на

new StringBuilder(string1).append(string2).toString()

т.е. создается new StringBuilder для объединения строк. Ваш второй вариант позволяет обойти эту проблему, поскольку он присоединяется непосредственно к существующему StringBuilder, избегая создания нового.

person arshajii    schedule 19.12.2013

Мы можем взглянуть на байт-код для каждой опции:

public class Concat {
    private static String s1 = "foo";
    private static String s2 = "bar";

    public static String good() {
        StringBuilder b = new StringBuilder();
        b.append(s1).append(s2);
        return b.toString();
    }

    public static String bad() {
        StringBuilder b = new StringBuilder();
        b.append(s1 + s2);
        return b.toString();
    }
}

$javap -c Concat.class

 public static java.lang.String good();
    Code:
       0: new           #2                  // class java/lang/StringBuilder
       3: dup           
       4: invokespecial #3                  // Method java/lang/StringBuilder."<init>":()V
       7: astore_0      
       8: aload_0       
       9: getstatic     #4                  // Field s1:Ljava/lang/String;
      12: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      15: getstatic     #6                  // Field s2:Ljava/lang/String;
      18: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      21: pop           
      22: aload_0       
      23: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      26: areturn       

  public static java.lang.String bad();
    Code:
       0: new           #2                  // class java/lang/StringBuilder
       3: dup           
       4: invokespecial #3                  // Method java/lang/StringBuilder."<init>":()V
       7: astore_0      
       8: aload_0       
       9: new           #2                  // class java/lang/StringBuilder
      12: dup           
      13: invokespecial #3                  // Method java/lang/StringBuilder."<init>":()V
      16: getstatic     #4                  // Field s1:Ljava/lang/String;
      19: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      22: getstatic     #6                  // Field s2:Ljava/lang/String;
      25: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      28: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      31: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      34: pop           
      35: aload_0       
      36: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      39: areturn

Ваш первый вариант фактически становится append(new StringBuilder().append(s1).append(s2).toString()).

person Jeffrey    schedule 19.12.2013

Первый текст быстрее набирается и во многих ситуациях легче читать.

Второй может работать немного лучше (согласно байт-коду Джеффри и объяснению Аршаджи).

Однако такая конкатенация строк вряд ли станет узким местом в вашей системе! Если производительность является проблемой, вам нужно профилировать. Компиляторы различаются. И улучшение алгоритмов обычно оказывает гораздо большее влияние, чем такая микрооптимизация.

Не выполняйте оптимизацию раньше, чем это необходимо! Действительно! Это так заманчиво и такая трата времени.

person ᴇʟᴇvᴀтᴇ    schedule 19.12.2013

Можно разумно ожидать, что будущее улучшение компилятора заставит обе альтернативы генерировать один и тот же код.

person Jonathan Rosenne    schedule 19.12.2013