Лучше ли использовать String.format над строкой Concatenation в Java?

Есть ли заметная разница между использованием String.Format и конкатенации строк в Java?

Я склонен использовать String.format но иногда выскальзываю и использую concat. Мне было интересно, лучше ли кто-то другой.

То, как я это вижу, String.Format дает вам больше силы в «форматировании» строки; и конкатенация означает, что вам не нужно беспокоиться о случайном вводе дополнительных% s или отсутствующих.

String.format также короче.

Какой из них более читабельный, зависит от того, как работает ваша голова.

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

    Если вы планируете локализовать свое приложение, вы также должны привыкнуть указывать позиции аргументов для ваших жетонов формата:

     "Hello %1$s the time is %2$t" 

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

     String.format("Hello %1$s, your name is %1$s and the time is %2$t", name, time) 

    О производительности:

     public static void main(String[] args) throws Exception { long start = System.currentTimeMillis(); for(int i = 0; i < 1000000; i++){ String s = "Hi " + i + "; Hi to you " + i*2; } long end = System.currentTimeMillis(); System.out.println("Concatenation = " + ((end - start)) + " millisecond") ; start = System.currentTimeMillis(); for(int i = 0; i < 1000000; i++){ String s = String.format("Hi %s; Hi to you %s",i, + i*2); } end = System.currentTimeMillis(); System.out.println("Format = " + ((end - start)) + " millisecond"); } 

    Результаты синхронизации следующие:

    • Конкатенация = 265 миллисекунд
    • Формат = 4141 миллисекунда

    Поэтому конкатенация выполняется намного быстрее, чем String.format.

    Поскольку есть дискуссия о производительности, я подумал, что добавлю в сравнение, в которое входит StringBuilder. Это на самом деле быстрее, чем concat и, естественно, опция String.format.

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

      String formatString = "Hi %s; Hi to you %s"; long start = System.currentTimeMillis(); for (int i = 0; i < 1000000; i++) { String s = String.format(formatString, i, +i * 2); } long end = System.currentTimeMillis(); log.info("Format = " + ((end - start)) + " millisecond"); start = System.currentTimeMillis(); for (int i = 0; i < 1000000; i++) { String s = "Hi " + i + "; Hi to you " + i * 2; } end = System.currentTimeMillis(); log.info("Concatenation = " + ((end - start)) + " millisecond"); start = System.currentTimeMillis(); for (int i = 0; i < 1000000; i++) { StringBuilder bldString = new StringBuilder("Hi "); bldString.append(i).append("; Hi to you ").append(i * 2); } end = System.currentTimeMillis(); log.info("String Builder = " + ((end - start)) + " millisecond"); 
    • 2012-01-11 16: 30: 46,058 INFO [TestMain] - Формат = 1416 миллисекунд
    • 2012-01-11 16: 30: 46,190 INFO [TestMain] - Конкатенация = 134 миллисекунды
    • 2012-01-11 16: 30: 46,313 INFO [TestMain] - String Builder = 117 миллисекунд

    Одна из проблем с .format заключается в том, что вы теряете безопасность статического типа. У вас может быть слишком много аргументов для вашего формата, и вы можете иметь неправильные типы для спецификаторов формата – оба они приводят к IllegalFormatException во время выполнения , поэтому вы можете получить код регистрации, который прерывает производство.

    Напротив, аргументы в + могут быть проверены компилятором.

    Какой из них более читабельный, зависит от того, как работает ваша голова.

    Вы получили свой ответ прямо там.

    Это вопрос личного вкуса.

    Полагаю, что конкатенация строк немного быстрее, но это должно быть незначительным.

    Вот тест с несколькими размерами выборки в миллисекундах.

     public class Time { public static String sysFile = "/sys/class/camera/rear/rear_flash"; public static String cmdString = "echo %s > " + sysFile; public static void main(String[] args) { int i = 1; for(int run=1; run <= 12; run++){ for(int test =1; test <= 2 ; test++){ System.out.println( String.format("\nTEST: %s, RUN: %s, Iterations: %s",run,test,i)); test(run, i); } System.out.println("\n____________________________"); i = i*3; } } public static void test(int run, int iterations){ long start = System.nanoTime(); for( int i=0;i "+ sysFile; } long t = System.nanoTime() - start; String r = String.format(" %-13s =%10d %s", "Concatenation",t,"nanosecond"); System.out.println(r) ; start = System.nanoTime(); for( int i=0;i ").append(sysFile); String s = b.toString(); } t = System.nanoTime() - start; r = String.format(" %-13s =%10d %s", "StringBuilder",t,"nanosecond"); System.out.println(r); } 

    }

     TEST: 1, RUN: 1, Iterations: 1 Concatenation = 14911 nanosecond Format = 45026 nanosecond StringBuilder = 3509 nanosecond TEST: 1, RUN: 2, Iterations: 1 Concatenation = 3509 nanosecond Format = 38594 nanosecond StringBuilder = 3509 nanosecond ____________________________ TEST: 2, RUN: 1, Iterations: 3 Concatenation = 8479 nanosecond Format = 94438 nanosecond StringBuilder = 5263 nanosecond TEST: 2, RUN: 2, Iterations: 3 Concatenation = 4970 nanosecond Format = 92976 nanosecond StringBuilder = 5848 nanosecond ____________________________ TEST: 3, RUN: 1, Iterations: 9 Concatenation = 11403 nanosecond Format = 287115 nanosecond StringBuilder = 14326 nanosecond TEST: 3, RUN: 2, Iterations: 9 Concatenation = 12280 nanosecond Format = 209051 nanosecond StringBuilder = 11818 nanosecond ____________________________ TEST: 5, RUN: 1, Iterations: 81 Concatenation = 54383 nanosecond Format = 1503113 nanosecond StringBuilder = 40056 nanosecond TEST: 5, RUN: 2, Iterations: 81 Concatenation = 44149 nanosecond Format = 1264241 nanosecond StringBuilder = 34208 nanosecond ____________________________ TEST: 6, RUN: 1, Iterations: 243 Concatenation = 76018 nanosecond Format = 3210891 nanosecond StringBuilder = 76603 nanosecond TEST: 6, RUN: 2, Iterations: 243 Concatenation = 91222 nanosecond Format = 2716773 nanosecond StringBuilder = 73972 nanosecond ____________________________ TEST: 8, RUN: 1, Iterations: 2187 Concatenation = 527450 nanosecond Format = 10291108 nanosecond StringBuilder = 885027 nanosecond TEST: 8, RUN: 2, Iterations: 2187 Concatenation = 526865 nanosecond Format = 6294307 nanosecond StringBuilder = 591773 nanosecond ____________________________ TEST: 10, RUN: 1, Iterations: 19683 Concatenation = 4592961 nanosecond Format = 60114307 nanosecond StringBuilder = 2129387 nanosecond TEST: 10, RUN: 2, Iterations: 19683 Concatenation = 1850166 nanosecond Format = 35940524 nanosecond StringBuilder = 1885544 nanosecond ____________________________ TEST: 12, RUN: 1, Iterations: 177147 Concatenation = 26847286 nanosecond Format = 126332877 nanosecond StringBuilder = 17578914 nanosecond TEST: 12, RUN: 2, Iterations: 177147 Concatenation = 24405056 nanosecond Format = 129707207 nanosecond StringBuilder = 12253840 nanosecond 

    Вот те же тесты, что и выше, с модификацией вызова метода toString () в StringBuilder . Результаты ниже показывают, что метод StringBuilder немного медленнее, чем конкатенация String с помощью оператора + .

    файл: StringTest.java

     class StringTest { public static void main(String[] args) { String formatString = "Hi %s; Hi to you %s"; long start = System.currentTimeMillis(); for (int i = 0; i < 1000000; i++) { String s = String.format(formatString, i, +i * 2); } long end = System.currentTimeMillis(); System.out.println("Format = " + ((end - start)) + " millisecond"); start = System.currentTimeMillis(); for (int i = 0; i < 1000000; i++) { String s = "Hi " + i + "; Hi to you " + i * 2; } end = System.currentTimeMillis(); System.out.println("Concatenation = " + ((end - start)) + " millisecond"); start = System.currentTimeMillis(); for (int i = 0; i < 1000000; i++) { StringBuilder bldString = new StringBuilder("Hi "); bldString.append(i).append("Hi to you ").append(i * 2).toString(); } end = System.currentTimeMillis(); System.out.println("String Builder = " + ((end - start)) + " millisecond"); } } 

    Команды Shell: (скомпилируйте и запустите StringTest 5 раз)

     > javac StringTest.java > sh -c "for i in \$(seq 1 5); do echo \"Run \${i}\"; java StringTest; done" 

    Результаты :

     Run 1 Format = 1290 millisecond Concatenation = 115 millisecond String Builder = 130 millisecond Run 2 Format = 1265 millisecond Concatenation = 114 millisecond String Builder = 126 millisecond Run 3 Format = 1303 millisecond Concatenation = 114 millisecond String Builder = 127 millisecond Run 4 Format = 1297 millisecond Concatenation = 114 millisecond String Builder = 127 millisecond Run 5 Format = 1270 millisecond Concatenation = 114 millisecond String Builder = 126 millisecond 

    String.format() больше, чем просто конкатенация строк. Например, вы можете отображать числа в определенной локали, используя String.format() .

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

    Я не сделал каких-либо конкретных тестов, но я думаю, что конкатенация может быть быстрее. String.format () создает новый Formatter, который, в свою очередь, создает новый StringBuilder (размером всего 16 символов). Это довольно много накладных расходов, особенно если вы форматируете более длинную строку и StringBuilder продолжает изменять размер.

    Однако конкатенация менее полезна и труднее читать. Как всегда, стоит сделать тест на свой код, чтобы узнать, что лучше. Различия могут быть незначительными в серверном приложении после того, как ваши пакеты ресурсов, локали и т. Д. Загружаются в память, а код – JITted.

    Возможно, в качестве лучшей практики было бы неплохо создать собственный Formatter с соответствующим размером StringBuilder (Appendable) и Locale и использовать его, если вам нужно много форматирования.

    Там может быть заметная разница.

    String.format довольно сложный и использует регулярное выражение под ним, поэтому не делайте привычкой использовать его везде, но только там, где он вам нужен.

    StringBuilder будет на порядок быстрее (как уже упоминалось ранее).

    Как правило, для String.format следует выбирать конкатенацию String.format . Последний имеет два основных недостатка:

    1. Он не кодирует строку, которая будет построена локально.
    2. Процесс построения закодирован в строке.

    В пункте 1 я имею в виду, что невозможно понять, что String.format() вызов String.format() за один последовательный проход. Один из них вынужден идти вперед и назад между строкой формата и аргументами, подсчитывая позицию аргументов. Для коротких конкатенаций это не большая проблема. Однако в этих случаях конкатенация строк менее многословна.

    В пункте 2 я подразумеваю, что важная часть процесса построения кодируется в строке формата (с использованием DSL). Использование строк для представления кода имеет много недостатков. Он не является по своей сути безопасным для текста и усложняет синтаксическую подсветку, анализ кода, оптимизацию и т. Д.

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

    Вы не можете сравнивать String Concatenation и String.Format в соответствии с вышеприведенной программой.

    Вы можете попробовать это также изменить позицию использования вашего String.Format и Concatenation в вашем блоке кода, как показано ниже.

     public static void main(String[] args) throws Exception { long start = System.currentTimeMillis(); for( int i=0;i<1000000; i++){ String s = String.format( "Hi %s; Hi to you %s",i, + i*2); } long end = System.currentTimeMillis(); System.out.println("Format = " + ((end - start)) + " millisecond"); start = System.currentTimeMillis(); for( int i=0;i<1000000; i++){ String s = "Hi " + i + "; Hi to you " + i*2; } end = System.currentTimeMillis(); System.out.println("Concatenation = " + ((end - start)) + " millisecond") ; } 

    Вы будете удивлены, увидев, что формат работает быстрее здесь. Это связано с тем, что созданные объекты не могут быть выпущены, и может возникнуть проблема с распределением памяти и, следовательно, с производительностью.

    Interesting Posts

    Могу ли я узнать возвращаемое значение перед возвратом во время отладки в Visual Studio?

    java.lang.NoClassDefFoundError: org / springframework / core / env / ConfigurableEnvironment

    Как обновить информацию в Android-активности из фоновой службы

    Как найти целевую версию Java для скомпилированного classа?

    Как проверить, запущен ли еще один экземпляр моего сценария оболочки

    Как включить приглашение классического входа в систему вместо экрана приветствия в Windows 7

    Целочисленный class-shell и оператор == – где указано поведение?

    Можно ли использовать адаптер питания для ноутбука с британским шнуром питания с сетевым шнуром США?

    C #: многострочный текст в элементе управления DataGridView

    Общая папка Только для чтения, но Анти-копия

    Где находится диск C в WSL?

    Как отключить запрос «Сохранить образ рабочего пространства?» В R?

    Загрузка файла ASP.NET MVC 3.0

    Можно ли заставить SSH передавать пустые аргументы?

    Как использовать Single TextWatcher для нескольких EditTexts?

    Давайте будем гением компьютера.