Конкатенация строк в Java StringBuilder

У меня есть устаревший Java-файл, который использует конкатенацию строк для создания огромных объектов String. Это серьезная проблема с производительностью. Есть метод как таковой, который делает следующее

String test="I am a very bad programmer"
+"to use concatenation"
+"Instead of StringBuilder"
+" or StringBuffer";

в

StringBuilder strBuilder= new StringBuilder();
strBuilder.append("I am a bad programmer");
strBuilder.append("to use concatenation");
strBuilder.append("Instead of StringBuilder");
strBuilder.append(" or StringBuffer");
String str= strBuilder.toString();

в основном мне нужна заглушка в Java, чтобы дать экземпляр String в качестве входных данных и преобразовать в StringBuilder. Кто-нибудь пробовал это в прошлом?

4 ответа

Решение

Фиксированный литерал, как в вашем примере, более эффективен, чем использование StringBuilder.

Фиксированный литерал будет обнаружен компилятором и будет встроен как одно значение, поэтому две строки

String s = "one" + "two" + "three";

а также

String s = "onetwothree";

сгенерирует точно такой же байт-код.

Хотя картина иная, если конкатенация выполняется не с литералами, а с вызовами функций.

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

Вот пример байт-кода:

общедоступный тест
{
   private String s = "one" + "two" + "three";
}

открытый класс Test2
{
   private String s2 = "onetwothree";
}

сгенерированный байт-код для этих классов:

c: \ Temp> тест javap -c
Скомпилировано из "Test.java"
Открытый класс Test расширяет java.lang.Object{
публичный тест ();
  Код:
   0:   aload_0
   1:   invokespecial   #1; // Метод java/lang/Object."":()V
   4:   aload_0
   5:   ldC#2; // Строка двухдневная
   7: путфилд № 3; // Поле s:Ljava/lang/String;
   10: возвращение
}
c:\Temp>javap -c Test2
Скомпилировано из "Test2.java"
открытый класс Test2 расширяет java.lang.Object{
public Test2();
  Код:
   0:   aload_0
   1:   invokespecial   #1; // Метод java/lang/Object."":()V
   4:   aload_0
   5:   ldC#2; // Строка двухдневная
   7: путфилд № 3; // Поле s:Ljava/lang/String;
   10: возвращение
}

Как видите, обе переменные обрабатываются одинаково.

Я не думаю, что это относится к спецификации языка, поскольку это "просто" оптимизация компилятора.

Другой компилятор (я использовал компилятор Sun) может делать что-то совершенно другое - это нормально, пока поведение не меняется.

Нет, это не проблема производительности. Если вы объединяете строку в строку (как вы показали), а не используете цикл, например, то компилятор автоматически преобразует + чтобы использовать StringBuilder, Проверьте документацию java.lang.String

Язык Java обеспечивает специальную поддержку оператора конкатенации строк ( +) и преобразования других объектов в строки. Конкатенация строк реализуется с помощью класса StringBuilder(или StringBuffer) и его метода добавления. Строковые преобразования осуществляются через метод toString, определяемый Object и наследуемый всеми классами в Java. Для получения дополнительной информации о конкатенации и преобразовании строк см. Гослинг, Джой и Стил, Спецификация языка Java.

Более того, компилятор может использовать тот факт, что все они являются строковыми константами, и присоединяться к ним даже до выполнения ( ссылки JLS).

На самом деле компилятор уже применяет эту оптимизацию для вас в последних версиях Java (по крайней мере, с версии 1.5, я думаю).

Что происходит, когда компилятор Java видит много конкатенаций строк в одной строке?

http://java.sun.com/docs/books/jls/third_edition/html/expressions.html

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

String example1 = "Префикс" + variableString1 + "Суффикс";

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

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

Другие вопросы по тегам