Czy lepiej jest używać Sznurka.formatowanie nad Konkatenacją łańcuchów w Javie?
Czy istnieje zauważalna różnica między używaniem String.Format
a konkatenacją łańcuchów w Javie?
Zazwyczaj używam String.format
ale czasami poślizgnę się i użyję konkat. Zastanawiałem się, czy jeden jest lepszy od drugiego.
Tak jak ja to widzę, String.Format
daje więcej mocy w "formatowaniu" ciągu; A konkatenacja oznacza, że nie musisz się martwić o przypadkowe dodanie dodatkowego % s lub pominięcie jednego.
String.format
jest również krótszy.
Który z nich jest bardziej czytelny zależy jak działa Twoja głowa.
12 answers
Sugerowałbym, że lepiej jest używać String.format()
. Głównym powodem jest to, że String.format()
może być łatwiej zlokalizowane za pomocą tekstu załadowanego z plików zasobów, podczas gdy konkatenacja nie może być zlokalizowana bez wytworzenia nowego pliku wykonywalnego z innym kodem dla każdego języka.
Jeśli planujesz, że Twoja aplikacja będzie możliwa do zlokalizowania, powinieneś również mieć zwyczaj określania pozycji argumentów dla tokenów formatu:
"Hello %1$s the time is %2$t"
To może być zlokalizowane i mieć nazwę i czas tokeny wymieniane bez konieczności rekompilacji pliku wykonywalnego w celu uwzględnienia różnych zamówień. W przypadku pozycji argumentów można również ponownie użyć tego samego argumentu bez dwukrotnego przekazywania go do funkcji:
String.format("Hello %1$s, your name is %1$s and the time is %2$t", name, time)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-13 17:27:17
O wydajności:
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");
}
Wyniki czasowe są następujące:
- konkatenacja = 265 milisekundy
- Format = 4141 milisekunda
Dlatego konkatenacja jest znacznie szybsza niż ciąg.format.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-22 23:25:00
Ponieważ jest dyskusja na temat wydajności, pomyślałem, że dodam do porównania, które obejmowało StringBuilder. Jest w rzeczywistości szybszy niż concat i, oczywiście, struna.opcja formatowania.
Aby zrobić to coś w rodzaju porównania jabłek do jabłek, tworzę instancję nowego Stringbuildera w pętli, a nie na zewnątrz (jest to w rzeczywistości szybsze niż robienie tylko jednej instancji, najprawdopodobniej ze względu na narzut realokacji miejsca dla pętli na końcu jednego z nich budowniczy).
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 milisekunda
- 2012-01-11 16:30:46,190 INFO [TestMain] - konkatenacja = 134 milisekunda
- 2012-01-11 16:30:46,313 INFO [TestMain] - String Builder = 117 milisekunda
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-11 22:47:02
Problem z .format
polega na tym, że tracisz bezpieczeństwo typu statycznego. Możesz mieć zbyt mało argumentów dla swojego formatu i możesz mieć niewłaściwe typy dla specyfikatorów formatu - oba prowadzą do IllegalFormatException
w czasie wykonywania , więc możesz skończyć z kodem logowania, który przerywa produkcję.
Natomiast argumenty +
mogą być testowane przez kompilator.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-23 21:52:29
Tu masz swoją odpowiedź. To kwestia gustu.Który z nich jest bardziej czytelny zależy od tego, jak działa Twoja głowa.
Konkatenacja łańcuchów jest nieznacznie szybsza, jak sądzę, ale to powinno być znikome.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-29 10:56:49
Oto test z wieloma rozmiarami próbek w milisekundach.
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-22 07:06:41
Oto ten sam test jak wyżej z modyfikacją wywołania toString() metoda Na Stringbuilderze . Poniższe wyniki pokazują, że podejście StringBuilder jest nieco wolniejsze niż łączenie łańcuchów za pomocą + centrala.
Plik: StringTest.JPG / StringTestjava
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");
}
}
polecenia powłoki: (skompiluj i uruchom StringTest 5 razy)
> javac StringTest.java
> sh -c "for i in \$(seq 1 5); do echo \"Run \${i}\"; java StringTest; done"
Wyniki :
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-03 21:29:33
String.format()
to coś więcej niż tylko łączenie strun. Na przykład, możesz wyświetlać liczby w określonych lokalizacjach za pomocą String.format()
.
Jeśli jednak nie zależy ci na lokalizacji, nie ma żadnej różnicy funkcjonalnej. Może jeden jest szybszy od drugiego, ale w większości przypadków będzie znikomy..
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-28 15:48:10
Nie zrobiłem żadnych konkretnych benchmarków, ale myślę, że konkatenacja może być szybsza. Sznurek.format() tworzy nowy program formatujący, który z kolei tworzy nowy StringBuilder (o rozmiarze tylko 16 znaków). To spora ilość narzutu, zwłaszcza jeśli formatujesz dłuższy ciąg, a StringBuilder musi zmieniać rozmiar.
Jednak konkatenacja jest mniej użyteczna i trudniejsza do odczytania. Jak zawsze, warto zrobić benchmark na swoim kodzie, aby zobaczyć, który jest lepszy. Na różnice mogą być znikome w aplikacji serwera po pakietach zasobów, lokalizacjach itp. są ładowane do pamięci i Kod jest JITted.
Być może jako najlepsza praktyka, dobrym pomysłem byłoby stworzenie własnego Formatera z odpowiednio dobranym Stringbuilderem (Appendable) i Locale i użycie tego, jeśli masz dużo formatowania do zrobienia.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-29 14:55:43
Może być zauważalna różnica.
String.format
jest dość złożony i używa wyrażenia regularnego pod spodem, więc nie rób z tego nawyku używać go wszędzie, ale tylko tam, gdzie go potrzebujesz.
StringBuilder
byłoby o rząd wielkości szybciej (jak ktoś tutaj już wskazał).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-10 08:19:55
Ogólnie rzecz biorąc, konkatenacja łańcuchów powinna być preferowana zamiast String.format
. Ten ostatni ma dwie główne wady:
- nie koduje łańcucha znaków, który ma być zbudowany w sposób lokalny.
- proces budowania jest zakodowany w łańcuchu znaków.
Przez punkt 1 mam na myśli, że nie można zrozumieć, co robi String.format()
wywołanie w jednym sekwencyjnym przejściu. Jeden jest zmuszony do przechodzenia tam iz powrotem między łańcuchem formatu a argumentami, podczas liczenia pozycji argumentów. W przypadku krótkich konkatenacji nie jest to zbyt duży problem. W tych przypadkach jednak konkatenacja łańcuchów jest mniej wyrazista.
Przez punkt 2 mam na myśli, że ważna część procesu budowania jest zakodowana w formacie string (za pomocą DSL). Używanie ciągów znaków do reprezentowania kodu ma wiele wad. Nie jest z natury bezpieczny dla typu i komplikuje podświetlanie składni, analizę kodu, optymalizację itp.
Oczywiście przy użyciu narzędzi lub frameworków zewnętrznych do języka Java, w grę mogą wchodzić nowe czynniki.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-02 13:41:12
Nie można porównywać konkatenacji łańcuchów i łańcuchów łańcuchowych.Formatowania według programu powyżej.
Możesz spróbować również zmienić pozycję używanego ciągu.Formatowanie i konkatenacja w bloku kodu jak poniżej
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") ;
}
Będziesz zaskoczony, widząc, że Format działa tutaj szybciej. Dzieje się tak, ponieważ utworzone obiekty intialne mogą nie zostać zwolnione i może wystąpić problem z alokacją pamięci, a tym samym wydajnością.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-29 04:37:35