Я тільки що зіткнувся StringBuilder
вперше і був здивований, оскільки Java вже має дуже потужний String
клас, який дозволяє додавати.
Чому другий String
клас?
Де я можу дізнатись більше StringBuilder
?
Я тільки що зіткнувся StringBuilder
вперше і був здивований, оскільки Java вже має дуже потужний String
клас, який дозволяє додавати.
Чому другий String
клас?
Де я можу дізнатись більше StringBuilder
?
Відповіді:
String
не дозволяє додавати. Кожен метод, який ви викликаєте в a, String
створює новий об'єкт і повертає його. Це тому, що String
є незмінним - він не може змінити свій внутрішній стан.
З іншого боку StringBuilder
є змінним. Коли ви викликаєте append(..)
це змінює внутрішній масив char, а не створює новий об'єкт рядка.
Таким чином, ефективніше мати:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 500; i ++) {
sb.append(i);
}
а не str += i
, що створить 500 нових рядкових об'єктів.
Зверніть увагу, що у прикладі я використовую цикл. Як зазначає helios у коментарях, компілятор автоматично перекладає вирази like String d = a + b + c
на щось подібне
String d = new StringBuilder(a).append(b).append(c).toString();
Зауважимо також, що є StringBuffer
крім StringBuilder
. Різниця полягає в тому, що перший має синхронізовані методи. Якщо ви використовуєте його як локальну змінну, використовуйте StringBuilder
. Якщо трапляється, що до нього можна отримати доступ з декількох потоків, використовуйте StringBuffer
(це рідше)
Ось конкретний приклад, чому -
int total = 50000;
String s = "";
for (int i = 0; i < total; i++) { s += String.valueOf(i); }
// 4828ms
StringBuilder sb = new StringBuilder();
for (int i = 0; i < total; i++) { sb.append(String.valueOf(i)); }
// 4ms
Як бачите, різниця в продуктивності значна.
s = sb.ToString();
в кінці, щоб принаймні ви зробили те саме в обох прикладах (результат a string
).
Клас рядка є незмінним, тоді як StringBuilder є змінним.
String s = "Hello";
s = s + "World";
Наведений вище код створить два об’єкти, оскільки рядок є незмінним
StringBuilder sb = new StringBuilder("Hello");
sb.append("World");
Наведений вище код створить лише один об'єкт, оскільки StringBuilder не є незмінним.
Урок: Всякий раз, коли виникає необхідність маніпулювати / оновлювати / додавати String багато разів, перейдіть до StringBuilder як його ефективного порівняно з String.
StringBuilder призначений для побудови рядків. Зокрема, будуючи їх дуже ефективно. Клас String підходить для багатьох речей, але насправді він має дійсно жахливі результати при складанні нового рядка з менших частин рядка, оскільки кожен новий рядок є абсолютно новим, перерозподіленим рядком. (Його незмінно ) StringBuilder зберігає ту саму послідовність і змінює її ( змінна ).
Клас StringBuilder можна змінювати, і на відміну від String, він дозволяє модифікувати вміст рядка без необхідності створювати більше об’єктів String, що може збільшити продуктивність, коли ви сильно модифікуєте рядок. Існує також аналог StringBuilder, який називається StringBuffer, який також синхронізований, тому він ідеально підходить для багатопоточних середовищ.
Найбільша проблема String полягає в тому, що будь-яка операція, яку ви робите з ним, завжди повертає новий об'єкт, скажімо:
String s1 = "something";
String s2 = "else";
String s3 = s1 + s2; // this is creating a new object.
StringBuilder добре, коли ви маєте справу з більшими рядками. Це допомагає вам покращити продуктивність.
Ось стаття, яку я виявив корисною.
Швидкий пошук у Google міг би вам допомогти. Зараз ви найняли 7 різних людей, щоб здійснити пошук у Google. :)
Якщо бути точним, StringBuilder додавання всіх рядків має значення O (N), а додавання String - O (N ^ 2). Перевірка вихідного коду це внутрішньо досягається збереженням змінного масиву символів. StringBuilder використовує техніку дублювання довжини масиву для досягнення амортизованої продуктивності O (N ^ 2) ціною потенційного подвоєння необхідної пам'яті. Ви можете зателефонувати trimToSize наприкінці, щоб вирішити цю проблему, але зазвичай об’єкти StringBuilder використовуються лише тимчасово. Ви можете додатково покращити продуктивність, надавши хороший початковий припущення щодо кінцевого розміру рядка.
Ефективність.
Кожного разу, коли ви об’єднуєте рядки, буде створюватися новий рядок. Наприклад:
String out = "a" + "b" + "c";
Це створює новий, тимчасовий рядок, копіює в нього "a" і "b", що приводить до "ab". Потім він створює ще один новий, тимчасовий рядок, копіює в нього "ab" і "c", щоб отримати "abc". Потім цей результат присвоюється out
.
Результатом є алгоритм Шлеміеля Пейнтера про складність часу O (n²) (квадратична).
StringBuilder
, з іншого боку, дозволяє додавати рядки на місце, змінюючи розмір вихідного рядка за необхідності.
Java має String, StringBuffer і StringBuilder:
Рядок: Його незмінна
StringBuffer: його змінні та безпечні потоки
StringBuilder: Його змінна, але не ThreadSafe, представлена в Java 1.5
Рядок, наприклад:
public class T1 {
public static void main(String[] args){
String s = "Hello";
for (int i=0;i<10;i++) {
s = s+"a";
System.out.println(s);
}
}
}
}
вихід: буде створено 10 різних рядків замість лише 1 рядка.
Helloa
Helloaa
Helloaaa
Helloaaaa
Helloaaaaa
Helloaaaaaa
Helloaaaaaaa
Helloaaaaaaaa
Helloaaaaaaaaa
Helloaaaaaaaaaa
StringBuilder, наприклад: Буде створено лише 1 об’єкт StringBuilder.
public class T1 {
public static void main(String[] args){
StringBuilder s = new StringBuilder("Hello");
for (int i=0;i<10;i++) {
s.append("a");
System.out.println(s);
}
}
}