Это лучшая практика, чтобы использовать string.формат конкатенации строк в Java?
есть ли заметная разница между использованием String.Format и конкатенация строк в Java?
Я предпочитаю использовать String.format но иногда будет скользить и использовать конкат. Мне было интересно, если один был лучше, чем другой.
как я это вижу,String.Format дает вам больше возможностей в "форматировании" строки; и конкатенация означает, что вам не нужно беспокоиться о случайном вводе дополнительного %s или его отсутствии.
String.format тоже укорачиваться.
какой из них более читаемый зависит от того, как работает ваша голова.
12 ответов:
Я бы предложил, что лучше использовать практику
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 МС
таким образом, конкатенация намного быстрее, чем строка.формат.
поскольку есть обсуждение производительности, я решил добавить в сравнение, которое включало StringBuilder. Это на самом деле быстрее, чем конкат и, естественно, строка.параметр форматирования.
чтобы сделать это своего рода сравнение яблок с яблоками, я создаю новый 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] - Format = 1416 миллисекунд
- 2012-01-11 16: 30: 46,190 INFO [TestMain] - Concatenation = 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<iterations; i++){ String s = "echo " + 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<iterations; i++){ String s = String.format(cmdString, i); } t = System.nanoTime() - start; r = String.format(" %-13s =%10d %s", "Format",t,"nanosecond"); System.out.println(r); start = System.nanoTime(); for( int i=0;i<iterations; i++){ StringBuilder b = new StringBuilder("echo "); b.append(i).append(" > ").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 немного медленнее, чем конкатенация строк с использованием + оператора.
file: 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"); } }команды оболочки: (компиляция и запуск 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().однако, если вы не заботитесь о локализации, нет функциональной разницы. Может быть, одно быстрее другого, но в большинстве случаев это будет незначительно..
Я не делал никаких конкретных критериев, но я думаю, что конкатенация может быть быстрее. Строка.format () создает новый форматер, который, в свою очередь, создает новый StringBuilder (с размером только 16 символов). Это довольно много накладных расходов, особенно если вы форматируете более длинную строку, и StringBuilder продолжает изменять размер.
однако конкатенация менее полезна и труднее читается. Как всегда, стоит сделать тест на вашем коде, чтобы увидеть, что лучше. Этот различия могут быть незначительными в серверном приложении после того, как ваши пакеты ресурсов, локали и т. д. загружаются в память, а код JITted.
возможно, как лучшая практика, было бы неплохо создать свой собственный форматер с соответствующим размером StringBuilder (Appendable) и Locale и использовать его, если у вас много форматирования.
может быть заметная разница.
String.formatдовольно сложен и использует регулярное выражение внизу, поэтому не делайте его привычкой использовать его везде, но только там, где вам это нужно.
StringBuilderбудет на порядок быстрее (как кто-то здесь уже указывал).
Как правило, конкатенация строк должна быть предпочтительнее
String.format. Последний имеет два основных недостатка:
- он не кодирует строку, которая должна быть построена локально.
- процесс построения кодируется в строку.
по пункту 1 я имею в виду, что невозможно понять, что такое
String.format()вызов выполняется за один последовательный проход. Один вынужден идти вперед и назад между строкой формата и аргументами, в то время как подсчет позиция аргументов. Для коротких конкатенаций это не большая проблема. Однако в этих случаях конкатенация строк менее подробна.по пункту 2, я имею в виду, что важная часть процесса строительства закодирована в формат строки (через DSL). Использование строк для представления кода имеет много недостатков. Он не является по своей сути типобезопасным и усложняет подсветку синтаксиса, анализ кода, оптимизацию и т. д.
конечно, при использовании инструменты или фреймворки, внешние для языка Java, могут вступать в игру новые факторы.
вы не можете сравнить конкатенацию строк и строку.Формат по этой программе.
вы можете попробовать это также поменять местами с помощью строки.Формат и конкатенация в вашем блоке кода, как показано ниже
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") ; }вы будете удивлены, увидев, что формат работает быстрее здесь. Это потому, что созданы исходные объекты не может быть освобожден и не может быть проблема с выделением памяти и тем самым производительность.
Comments