Конкатенация строк в 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 + "Суффикс";
худший случай - циклы с добавлением, где каждая итерация должна создать новую строку. Так как это является обычным для буферизованного чтения файлов, вы можете получить очень большие строки при воссоздании, проблема, с которой я недавно столкнулся.
Хотя я понимаю, почему вы хотите делать то, что делаете, структуры кода слишком разные, чтобы их можно было просто вставить и заменить, и сценарий для редактирования кода должен быть достаточно продвинутым, чтобы иметь возможность справляться со всеми Рекомендации. Может быть, есть способ с аннонимными внутренними классами, хотя это может позволить вам сохранить ту же ссылку на строку, но обернуть фактическую конструкцию в компоновщики строк. Это, вероятно, ничем не отличается от того, что оптимизатор уже делает, хотя