Сначала мы должны вспомнить характеристики трех:
1. Определение
Посмотрев на API, вы найдете эту строку, StringBuffer и StringBuilder, все реализуют интерфейс ChareSequence. Хотя все они связаны с струнами, их механизмы обработки различны.
2. Используйте сценарии
Сценарии с использованием класса строк: в сценариях, где строки не часто меняются, можно использовать классы строк, такие как объявления константы и небольшое количество операций переменных.
Сценарии с использованием класса StringBuffer: когда строковые операции часто выполняются (например, сплайсинг, замена, удаление и т. Д.) И работают в многопоточной среде, вы можете рассмотреть возможность использования StringBuffer, такого как парирование XML, парирование параметров HTTP и инкапсуляция.
Сценарии с использованием класса StringBuilder: когда строковые операции часто выполняются (такие как сплайсинг, замена и делеция), и работают в однопоточной среде, вы можете рассмотреть возможность использования StringBuilder, такого как сборка операторов SQL, инкапсуляция JSON и т. Д.
Iii. Анализ
Проще говоря, основная разница в производительности между типом строки и типом StringBuffer на самом деле заключается в том, что строка является неизменным объектом, поэтому каждый раз, когда вы меняете тип строки, она фактически эквивалентна генерации нового строкового объекта, а затем указывает указатель на новый объект строки. Следовательно, лучше не использовать строки для строк, которые часто изменяют контент, потому что каждое поколение объектов окажет влияние на производительность системы, особенно когда в памяти слишком много ссылочных объектов, GC JVM начнет работать, что определенно будет довольно медленным.
Если вы используете класс StringBuffer, результат будет другим. Каждый раз, когда результат будет работать на самом объекте StringBuffer, вместо того, чтобы генерировать новый объект, а затем изменять ссылку объекта. Поэтому, в целом, мы рекомендуем использовать StringBuffer, особенно когда строки часто меняются. В некоторых особых случаях строковая сплайсинг строковых объектов фактически интерпретируется JVM как сплайсинг объектов StringBuffer. Следовательно, скорость строковых объектов не более медленнее, чем объекты StringBuffer в настоящее время. Особенно в следующей генерации объектов строковых объектов эффективность строки намного быстрее, чем StringBuffer:
String S1 = "Это только" + "простой" + "тест"; stringBuffer sb = new StringBuilder ("Это только A"). Append ("simple"). Append ("test");Вы будете удивлены, обнаружив, что скорость генерации объектов S1 S1 просто слишком быстра, и в настоящее время StringBuffer не имеет никакого преимущества в скорости. На самом деле, это хитрость JVM. В глазах JVM это
Строка S1 = "Это только тест" + "простой" + ";
На самом деле:
String S1 = "Это только простой тест";
Так что, конечно, это не займет много времени. Но вы должны отметить, что если ваша строка поступает из другого объекта String, скорость не такая быстрая, например:
String S2 = "Это только A"; String S3 = "Simple"; String S4 = "test"; String S1 = S2 + S3 + S4;
В настоящее время JVM будет делать это регулярно в оригинале.
4. Глубокая оптимизация и обработка JVM
Есть ли на самом деле вышеуказанная стоимость производительности? Спилочный сплайсинг в строке так распространен, нет ли специальной оптимизации обработки? Ответ заключается в том, что эта оптимизация выполняется при компиляции .java к байткоду в JVM.
Если программа Java хочет запустить, потребуется два периода, время компиляции и время выполнения. Во время компиляции Java JVM (компилятор) преобразует файл Java в ByteCode. Во время выполнения виртуальная машина Java (JVM) запускает сгенерированный временем компиляции. Через эти два периода Java достигла так называемой компиляции и работает повсюду.
Давайте экспериментируем с тем, какие оптимизации были сделаны в течение периода компиляции, и мы создаем кусок кода, который может иметь затраты на производительность.
public Class Concatenation {public static void main (string [] args) {string username = "andy"; String Age = "24"; String job = "Разработчик"; String info = имя пользователя + возраст + job; System.out.println (info); }}Компилирование Concatenation.java. Получить concatenation.class
Javac Concatenation.java
Затем мы используем Javap для декомпиляции скомпилированного файла concatenation.class. Javap -c Concatenation. Если команда Javap не найдена, пожалуйста, рассмотрите возможность добавления каталога, в котором Javap расположен в переменной среды или с использованием полного пути Javap.
17: 22: 04 -androidyue ~/workpace_adt/strings/src $ javap -c concatenationcompilled из "concatenation.java" public Class Concatenation {public concatenation (); Код: 0: aload_0 1: infokpescial #1 // Метод Java/Lang/Object. Код: 0: LDC #2 // String Andy 2: Store_1 3: LDC #3 // String 24 5: Store_2 6: LDC #4 // Строка разработчика 8: Store_3 9: новый #5 // класс Java/Lang/StringBuilder 12: Dup 13: Invokespecial #6 // Method Java/Lang/StringBuilder. InvokeVirtual #7 // Метод java/lang/stringbuilder.append: (ljava/lang/string;) ljava/lang/stringbuilder; 20: aload_2 21: Invokevirtual #7 // Метод Java/lang/stringBuilder.append: (ljava/lang/string;) ljava/lang/stringbuilder; 24: aload_3 25: Invokevirtual #7 // Метод java/lang/stringbuilder.append: (ljava/lang/string;) ljava/lang/stringbuilder; 28: InvokeVirtual #8 // Метод java/lang/stringbuilder.tostring :() ljava/lang/string; 31: Магазин 4 33: GetStatic #9 // Полевой java/lang/system.out: ljava/io/printstream; 36: Aload 4 38: Invokevirtual #10 // Метод Java/io/printStream.println: (ljava/lang/string;) v 41: return}Среди них, НРС, магазин и т. Д. Имеются инструкции по байт -коде Java, аналогичные инструкциям сборки. В следующих комментариях используется контент, связанный с Java для объяснения. Мы видим, что на нем много строк, но мы называем их в коде Java без отображения. Это оптимизация, сделанная Javajvm. Когда Javajvm встречает сплайсинг строки, будет создан объект StringBuilder. Сплайсинг, стоящий за ним, на самом деле вызывает метод добавления объекта StringBuilder. Таким образом, не будет никаких проблем, о которых мы беспокоимся.
5. Полагаться только на оптимизацию JVM?
Поскольку JVM помог нам оптимизировать, достаточно ли этого, чтобы полагаться исключительно на оптимизацию JVM? Конечно, нет.
Давайте посмотрим на кусок кода, который не был оптимизирован для низкой производительности
public void imploiceSestringBuilder (string [] values) {String result = ""; for (int i = 0; i <values.length; i ++) {result += values [i]; } System.out.println (result);}Скомпилируйте Javac и просмотрите с помощью Javap
public void imploiceSestringBuilder (java.lang.string []); Код: 0: LDC #11 // String 2: Store_2 3: ICONST_0 4: ISTORE_3 5: ILOAD_3 6: ALOAD_1 7: ArrayLength 8: IF_ICMPGE 38 11: NEW #5 // Class Java/Lang/StringBuilder 14: DUP 15: Invokespecial #6 // Метод Java/langbu/stringb 18: aload_2 19: Invokevirtual #7 // Метод Java/lang/StringBuilder.append: (ljava/lang/string;) ljava/lang/stringbuilder; 22: aload_1 23: iload_3 24: aaload 25: Invokevirtual #7 // Метод java/lang/stringbuilder.append: (ljava/lang/string;) ljava/lang/stringbuilder; 28: InvokeVirtual #8 // Метод java/lang/stringbuilder.tostring :() ljava/lang/string; 31: Store_2 32: IINC 3, 1 35: GOTO 5 38: GETSTATIC #9 // Полевой java/lang/system.out: ljava/io/printstream; 41: aload_2 42: Invokevirtual #10 // Метод Java/io/printstream.println: (ljava/lang/string;) V 45: return
Среди них 8: if_icmpge 38 и 35: goto 5 образуют цикл. 8: IF_ICMPGE 38 означает, что если целочисленное сравнение стека операнда JVM больше или равно (I <противоположный результат значений. 35: GOTO 5 означает прыгать прямо на строку 5.
Но здесь есть очень важная вещь, что создание объекта StringBuilder происходит между петлями, что означает, что сколько раз петли будут создавать несколько объектов StringBuilder, что, очевидно, не очень хорошо. Голый код низкого уровня.
Оптимизируйте его немного, чтобы мгновенно улучшить качество.
public void explicitUseStringBuilder (string [] values) {stringBuilder result = new StringBuilder (); for (int i = 0; i <values.length; i ++) {result.append (values [i]); }}Соответствующая скомпилированная информация
11: Aload_1 12: ArrayLength 13: if_icmpge 30 16: aload_2 17: aload_1 18: iload_3 19: aaload 20: invokevirtual #7 // Метод java/lang/stringbuilder.append: (ljava/lang/string;) ljava/lang/stringbuilder; 23: Pop 24: iinc 3, 1 27: goto 10 30: return
Как можно увидеть сверху, 13: if_icmpge 30 и 27: goto 10 образуют петлю петли, а 0: новый #5 находится за пределами цикла, поэтому StringBuilder не создается несколько раз.
В целом, мы должны попытаться избежать неявного или явного создания строк -строителей в теле петли. Поэтому те, кто понимает, как составлен код и как он выполняется внутри, имеют относительно высокие уровни кода.
6. Заключение
В большинстве случаев StringBuffer> строка
Java.lang.stringbuffer-это безопасная последовательность символов переменных. Строковый буфер строк, но не может быть изменен. Хотя он содержит определенную последовательность символов в любой момент времени, длина и содержание последовательности могут быть изменены некоторыми вызовами метода. Буферы струн могут безопасно использовать в программах для многопоточного чтения. И эти методы могут быть синхронизированы при необходимости, поэтому все операции в любом конкретном случае, по -видимому, происходят в последовательном порядке, который согласуется с порядком вызовов методов, выполненных каждым вовлеченным потоком.
Основными операциями на StringBuffer являются методы добавления и вставки, которые могут быть перегружены, чтобы принять любой тип данных. Каждый метод может эффективно преобразовать заданные данные в строку, а затем добавить или вставить символы этой строки в буфер строки. Метод добавления всегда добавляет эти символы к концу буфера; Метод вставки добавляет символы в указанной точке.
Например, если z относится к строковому буферному объекту, текущий содержимое которого является «запуск», этот метод Call Z.Append («le») заставит строковый буфер содержит «испуг» (накопленный); и Z.Insert (4, «le») изменит буфер строк, чтобы содержать «звездочку».
В большинстве случаев StringBuilder> StringBuffer
java.lang.stringbuilder Переменная последовательность символов является новой в Java 5.0. Этот класс предоставляет API-совместимый с StringBuffer API, но не гарантированно будет синхронизирован, поэтому сценарий использования является одним резьбом. Этот класс предназначен для простой замены для StringBuffer, когда строковые буферы используются одним потоком (это обычно). Если возможно, рекомендуется первым заняться этим классом, так как он быстрее, чем StringBuffer в большинстве реализаций. Методы использования обоих в основном одинаковы.