Próbuję zrozumieć, jakie są najlepsze praktyki i dlaczego należy łączyć literały ciągów i zmienne dla różnych przypadków. Na przykład, jeśli mam taki kod
StringBuilder sb = new StringBuilder("AAAAAAAAAAAAA")
.append(B_String).append("CCCCCCCCCCC").append(D_String)
.append("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
.append("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
Czy to jest sposób na zrobienie tego? W tym poście zauważyłem, że +
operator w Strings tworzy nową instancję StringBuilder, łączy operandy i zwraca konwersję typu String, która wydaje się być o wiele bardziej wymagająca niż zwykłe wywołanie .append()
; więc jeśli to prawda, to nie wchodzi w rachubę. Ale co z tym String.concat()
? Czy jest to właściwe .append()
dla każdego konkatenacji? A może tylko dla zmiennych, a literały można dołączyć .concat()
?
StringBuilder sb = new StringBuilder("AAAAAAAAAAAAA")
.append(B_String.concat("CCCCCCCCCCC")).append(D_String
.concat("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
.concat("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
Jakie są ogólne zasady dotyczące najlepszych praktyk i wydajności w takich sytuacjach? Czy moje założenie jest słuszne +
i naprawdę nie powinno być używane?
źródło
Odpowiedzi:
+
operatorZa kulisami jest to przetłumaczone na:
String s = new StringBuilder(s1).append(s2).toString();
Wyobraź sobie, ile dodatkowej pracy to dodaje, jeśli masz
s1 + s2
tutaj:zamiast:
Wiele ciągów z
+
Warto zauważyć, że:
jest tłumaczone na:
String s = new StringBuilder(s1).append(s2).append(s3)...apend(sN).toString();
concat()
String
tworzychar[]
tablicę, która może pasować zarówno do, jaks1
is2
. Kopies1
is2
zawartość do tej nowej tablicy. Właściwie wymaga mniej pracy niż+
operator.StringBuilder.append()
Utrzymuje wewnętrzną
char[]
tablicę, która rośnie w razie potrzeby.char[]
Jeśli wewnętrzna jest wystarczająco duża, nic nie jest tworzone.jest również mało skuteczne, ponieważ
s1.concat(s2)
tworzy dodatkowąchar[]
tablicę i kopies1
is2
do niego po prostu skopiować, że nowe zawartość tablicy do wewnętrznejStringBuilder
char[]
.Mając to na uwadze, powinieneś używać przez
append()
cały czas i dołączać nieprzetworzone ciągi (Twój pierwszy fragment kodu jest poprawny).źródło
+
na obiektach String zamiast tworzyćStringBuilder
dla tej jednorazowej konkatenacji, ponieważ zasadniczo zrobi to samo?Kompilator optymalizuje + konkatenację.
Więc
int a = 1; String s = "Hello " + a;
jest przekształcany w
new StringBuilder().append("Hello ").append(1).toString();
Jest tutaj doskonały temat wyjaśniający, dlaczego powinieneś używać operatora +.
źródło
String s = "Hello World";
ponieważ używasz literałów.Optymalizacja jest wykonywana automatycznie przez kompilator.
Kompilator Java2 automatycznie skonwertuje następujące elementy:
do
String s = (new StringBuffer()).append(s1).append(s2).toString();
Zaczerpnięte prosto z witryny Java Best Practices on Oracles.
źródło
Powinieneś zawsze używać
append
.concat
stwórz nowy ciąg, żeby wyglądał całkiem tak+
, jak myślę.Jeśli
concat
używasz+
z 2 końcowymi ciągami znaków, JVM może dokonać optymalizacji, więc jest to to samo, co dodanie w tym przypadku.źródło
Jeśli połączysz dokładnie dwa Strings, użyj String.concat (tworzy nowy String, tworząc nową tablicę znaków, która pasuje do obu Strings i kopiuje do niej tablice char obu Strings).
Jeśli połączysz wiele (więcej niż dwa) ciągów w jednym wierszu, użyj + lub StringBuilder.append, nie ma to znaczenia, ponieważ kompilator konwertuje + na StringBuilder.append. Jest to dobre dla wielu ciągów, ponieważ utrzymuje jedną tablicę znaków, która rośnie w razie potrzeby.
Jeśli łączysz wiele ciągów w wielu wierszach, utwórz jeden StringBuilder i użyj metody append. Na koniec, gdy skończysz dołączać ciągi do obiektu StringBuilder, użyj jego metody .toString (), aby utworzyć z niego String. W przypadku łączenia w wielu wierszach jest to szybsze niż druga metoda, ponieważ druga metoda utworzyłaby nowy StringBuilder w każdym wierszu, dołączyłby ciągi, a następnie rzutowałby z powrotem na String, podczas gdy trzecia metoda używa tylko jednego StringBuildera do całości.
źródło
Użyj
+
operatora jest najlepszą praktyką, jest również prosty i czytelny.Oficjalny dokument: https://docs.oracle.com/javase/8/docs/api/java/lang/String.html
źródło
na poziomie kodu bajtowego nie ma różnicy i nie narażamy tam wydajności. W przypadku wykonywania kodu bajtowego musi przejść przez metodę przeciążania operatora nieliniowego dla +, wywołując append. następnie na poziomie języka asemblera (Java jest napisana w C, a C tworzy zestawy podobne do asemblera, będzie dodatkowe wywołanie rejestru do przechowywania + wywołanie metody na stosie i dodatkowe wypychanie. (w rzeczywistości kompilator krzyżowy może optymalizować + operator zadzwonić, w takim przypadku nie ma to znaczenia dla skuteczności).
Dobrą praktyką jest posiadanie jednego sposobu na zwiększenie czytelności. :)
źródło
Osobiście wolę
Strings.format()
prosty, czytelny, jednowierszowy program do formatowania ciągów .String b = "B value"; String d = "D value"; String fullString = String.format("A %s C %s E F", b, d); // Output: A B value C D value E F
źródło
Wszystkie odpowiedzi są całkiem dobre i wyjaśniające. Ale czułem, że badanie innych technik łączenia strun również może pomóc, takich jak - Guava Joiner, Streams, String.format itp.
Aby uzyskać szczegółowe informacje na temat wydajności każdej techniki konkatenacji, java-string-concatenation-which-way-is-best .
W skrócie, wydajność konkatenacji zmienia się bez. ciągów do konkatenacji. Na przykład - aby połączyć 1-10 ciągów, te techniki działają najlepiej - StringBuilder, StringBuffer i Operator Plus. Aby połączyć setki strun - Guava Joiner, biblioteka apache's stringsUtils również działa świetnie.
Przejdź przez powyższy blog. To naprawdę bardzo dobrze wyjaśnia wydajność wydajności.
Dzięki.
źródło