Конкатенация строк, а затем добавить в цикл - PullRequest
0 голосов
/ 03 сентября 2018

Найден этот отрывок из книги "Мышление на Яве", написанной Брюсом Эккелем.

Если вы попытаетесь использовать ярлыки и сделать что-то вроде append(a + ": " + c) компилятор перейдет на и начнет делать more StringBuilder объекты снова.

Означает ли это, что мы не должны заменять группу операций добавления одной строкой кода; например, result.append(i + ": " + 2*i + " ")?

StringBuilder result = new StringBuilder();
for(int i = 0; i < 25; i++) {
    result.append(i);
    result.append(": ");
    result.append(2*i);
    result.append(", ") 
}

Приведенное выше утверждение верно и для Java 8?

Отрывок из этого ответа на SO: (еще больше смутил)

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

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

Ответы [ 3 ]

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

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

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

IntStream
    .range(0, 25)
    .map(i, String.format("%d: %d", i, i*2)
    .collect(Collectors.joining(", "));
0 голосов
/ 03 сентября 2018

По сути, компилятор заменяет экземпляры String конкатенации на StringBuilder s, поэтому ваша строка

result.append(i + ": " + 2*i + " ");

Изменено на

result.append(new StringBuilder().append(i).append(": ").append(2*i).append(" ").toString());

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

Так что да, определенно было бы лучше просто добавить к StringBuilder, который у вас уже есть, вместо объединения. Независимо от того, делаете ли вы это в одной беглой строке, это в основном вопрос предпочтений.

Я не уверен, что ответ, который вы нашли, означает "не может заменить StringBuilder". Возможно, они имели в виду, что он не будет повторно использовать ваш существующий компоновщик (и вместо этого создаст новый).

Это все еще действует для Java 8, хотя с тех пор существуют альтернативные методы потоковой передачи, как показывает один из других ответов.

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

Это не оптимизация, которую компилятор сделает для вас эффективно. Стилистически я бы написал так:

StringBuilder result = new StringBuilder();
for (int i = 0; i < 25; i++) {
    result.append(i).append(": ").append(2 * i).append(", ");
}

ПРИМЕЧАНИЕ: IDE, такие как IntelliJ, обнаружат и предоставят автоматическое исправление для этого, так как это обычный перевод.

...