StringBuilder против конкатенации строк в toString () в Java

Трюк заключается в том, чтобы помнить, что данные private относятся к классу, а не к экземпляру класса. Любой метод внутри вашего класса может получить доступ к личным данным любого экземпляра этого класса; не существует способа держать данные конфиденциальными внутри экземпляра, если вы не запрещаете методы, которые явно получают доступ к частным данным из других экземпляров.

857
задан medvedev1088 9 September 2016 в 19:33
поделиться

9 ответов

Версия 1 предпочтительнее, потому что она короче и компилятор фактически превратит ее в версию 2 - никакой разницы в производительности нет.

Что еще более важно, учитывая, что у нас есть только 3 свойства это может не сделать разница, но в какой момент ты переключиться с concat на построитель?

В точке, где вы объединяете в цикл - обычно это когда компилятор не может самостоятельно заменить StringBuilder .

927
ответ дан 22 November 2019 в 21:06
поделиться

Вот то, что я зарегистрировался в Java8

  • Используя Конкатенацию строк
  • Используя StringBuilder

    long time1 = System.currentTimeMillis();
    usingStringConcatenation(100000);
    System.out.println("usingStringConcatenation " + (System.currentTimeMillis() - time1) + " ms");
    
    time1 = System.currentTimeMillis();
    usingStringBuilder(100000);
    System.out.println("usingStringBuilder " + (System.currentTimeMillis() - time1) + " ms");
    
    
    private static void usingStringBuilder(int n)
    {
        StringBuilder str = new StringBuilder();
        for(int i=0;i<n;i++)
            str.append("myBigString");    
    }
    
    private static void usingStringConcatenation(int n)
    {
        String str = "";
        for(int i=0;i<n;i++)
            str+="myBigString";
    }
    

, Это - действительно кошмар при использовании конкатенации строк для большого количества строк.

usingStringConcatenation 29321 ms
usingStringBuilder 2 ms
1
ответ дан 22 November 2019 в 21:06
поделиться

] Могу я указать, что если вы собираетесь перебирать коллекцию и использовать StringBuilder, вы можете проверить Apache Commons Lang и StringUtils.join () (в разных ароматы)?

Независимо от производительности, это избавит вас от необходимости создавать StringBuilders и циклы for для того, что кажется миллионным разом.

1
ответ дан 22 November 2019 в 21:06
поделиться

Для таких простых строк я предпочитаю использовать

"string".concat("string").concat("string");

По порядку, я бы сказал, что предпочтительным методом построения строки является использование StringBuilder, String # concat (), а затем перегруженного оператора + . StringBuilder - это значительное увеличение производительности при работе с большими строками, так же как использование оператора + приводит к значительному снижению производительности (экспоненциально большое уменьшение при увеличении размера String). Единственная проблема с использованием .concat () заключается в том, что он может генерировать исключения NullPointerExceptions.

-4
ответ дан 22 November 2019 в 21:06
поделиться

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

public class Main
{
    public static void main(String[] args)
    {
        long now = System.currentTimeMillis();
        slow();
        System.out.println("slow elapsed " + (System.currentTimeMillis() - now) + " ms");

        now = System.currentTimeMillis();
        fast();
        System.out.println("fast elapsed " + (System.currentTimeMillis() - now) + " ms");
    }

    private static void fast()
    {
        StringBuilder s = new StringBuilder();
        for(int i=0;i<100000;i++)
            s.append("*");      
    }

    private static void slow()
    {
        String s = "";
        for(int i=0;i<100000;i++)
            s+="*";
    }
}

Результат:

slow elapsed 11741 ms
fast elapsed 7 ms

Проблема в том, что to + = append к строке восстанавливает новую строку, поэтому она стоит чего-то линейного в зависимости от длины ваших строк (суммы обеих).

Итак - на ваш вопрос:

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

71
ответ дан 22 November 2019 в 21:06
поделиться

Сделайте метод toString максимально читаемым!

Единственное исключение в моей книге - это если вы докажете мне , что он потребляет значительные ресурсы :) (Да, это означает профилирование)

Также обратите внимание, что компилятор Java 5 генерирует более быстрый код, чем рукописный подход StringBuffer, использовавшийся в более ранних версиях Java. Если вы используете "+", это и последующие улучшения будут бесплатными.

4
ответ дан 22 November 2019 в 21:06
поделиться

Я предпочитаю:

String.format( "{a: %s, b: %s, c: %s}", a, b, c );

... потому что он короткий и удобочитаемый.

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

] Я согласен, что если вам нужно вывести много параметров, эта форма может запутаться (как сказано в одном из комментариев). В этом случае я бы переключился на более читаемую форму (возможно, используя ToStringBuilder из apache-commons - взято из ответа matt b) и снова проигнорирую производительность.

эта форма может сбивать с толку (как сказано в одном из комментариев). В этом случае я бы переключился на более читаемую форму (возможно, используя ToStringBuilder из apache-commons - взято из ответа matt b) и снова проигнорирую производительность.

эта форма может сбивать с толку (как сказано в одном из комментариев). В этом случае я бы переключился на более читаемую форму (возможно, используя ToStringBuilder из apache-commons - взято из ответа matt b) и снова проигнорирую производительность.

74
ответ дан 22 November 2019 в 21:06
поделиться

Apache Commons-Lang имеет класс ToStringBuilder , который очень прост в использовании. Он отлично справляется как с обработкой логики добавления, так и с форматированием того, как вы хотите, чтобы ваш toString выглядел.

public void toString() {
     ToStringBuilder tsb =  new ToStringBuilder(this);
     tsb.append("a", a);
     tsb.append("b", b)
     return tsb.toString();
}

Вернет результат, который выглядит как com.blah.YourClass@abc1321f [a = любой, b = foo] .

Или в более сжатой форме с использованием цепочки:

public void toString() {
     return new ToStringBuilder(this).append("a", a).append("b", b").toString();
}

Или, если вы хотите использовать отражение для включения всех полей класса:

public String toString() {
    return ToStringBuilder.reflectionToString(this);
}

Вы также можете настроить стиль ToString, если вы хотите.

7
ответ дан 22 November 2019 в 21:06
поделиться

Ключ в том, пишете ли вы единую конкатенацию в одном месте или накапливать его с течением времени.

В приведенном вами примере нет смысла явно использовать StringBuilder. (Посмотрите на скомпилированный код для вашего первого случая.)

Но если вы строите строку, например, внутри цикла, используйте StringBuilder.

Чтобы уточнить, предполагая, что огромныйArray содержит тысячи строк, используйте следующий код:

...
String result = "";
for (String s : hugeArray) {
    result = result + s;
}

очень затратно по времени и памяти по сравнению с:

...
StringBuilder sb = new StringBuilder();
for (String s : hugeArray) {
    sb.append(s);
}
String result = sb.toString();
239
ответ дан 22 November 2019 в 21:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: