Как StringBuffer реализует функцию append без создания двух объектов?
Это был вопрос интервью. Меня попросили реализовать функцию StringBuffer
append. После интервью я увидел код. Но я не могу понять, как выполняется операция с созданием одного объекта.
Я так думаю.
String s = "orange";
s.append("apple");
Здесь создаются два объекта.
Но
StringBuilder s = new StringBuilder("Orange");
s.append("apple");
Теперь здесь создается только один объект.
Как работает эта операция Java?
Ответы
Ответ 1
Сначала возникает проблема с вашим вопросом:
String s = "orange";
s.append("apple");
здесь создаются два объекта
Правильно, создаются два объекта, строка "оранжевый" и строка "яблоко", внутри StringBuffer/StringBuilder no Objects будут созданы, если мы не переполним буфер. Таким образом, эти строки кода создают 2 или 3 объекта.
StringBuilder s = new StringBuilder("Orange");
s.append("apple");
Теперь здесь создается только один объект
Я не знаю, где вы это понимаете, здесь вы создаете один объект StringBuilder, одну "оранжевую" строку, одну "яблочную" строку, всего 3 объекта или 4, если мы переполним буфер StringBuilder. (Я считаю создание массива как создание объекта).
Я прочитал ваш вопрос: как StringBuilder может добавить приложение без создания нового объекта (когда буфер не переполнен)?
Вы должны посмотреть StringBuilder
, так как это небезопасная реализация. Код интересен и прост в чтении. Я добавил комментарии inline.
В качестве внутренней структуры существует массив char, а не строка. Он изначально построен с длиной 16 и будет увеличен каждый раз, когда мощность будет превышена. Если строки для добавления в массив char не нужно создавать новые объекты.
StringBuilder
extends AbstractStringBuilder
, где вы найдете следующий код:
/**
* The value is used for character storage.
*/
char value[];
Поскольку не весь массив будет использоваться в данный момент времени, другой важной переменной будет длина:
/**
* The count is the number of characters used.
*/
int count;
Существует много перегрузок append, но наиболее интересным является следующее:
public AbstractStringBuilder append(String str) {
if (str == null) str = "null"; //will literally append "null" in case of null
int len = str.length(); //get the string length
if (len == 0) return this; //if it zero, I'm done
int newCount = count + len; //tentative new length
if (newCount > value.length) //would the new length fit?
expandCapacity(newCount); //oops, no, resize my array
str.getChars(0, len, value, count); //now it will fit, copy the chars
count = newCount; //update the count
return this; //return a reference to myself to allow chaining
}
String.getChars (int srcBegin, int srcEnd, char [] dst, int dstBegin) Копирует символы из этой строки в пункт назначения массив символов.
Итак, метод append довольно прост, единственное, что осталось открыть, - это expandCapacity
, вот оно:
void expandCapacity(int minimumCapacity) {
//get the current length add one and double it
int newCapacity = (value.length + 1) * 2;
if (newCapacity < 0) { //if we had an integer overflow
newCapacity = Integer.MAX_VALUE; //just use the max positive integer
} else if (minimumCapacity > newCapacity) { //is it enough?
//if doubling wasn't enough, use the actual length computed
newCapacity = minimumCapacity;
}
//copy the old value in the new array
value = Arrays.copyOf(value, newCapacity);
}
Arrays.copyOf (char [] original, int newLength) Копирует указанный массив, обрезает или дополняет нулевые символы (при необходимости), поэтому копия имеет указанную длину.
В нашем случае прокладка, так как мы расширяем длину.
Ответ 2
Источником является ваш друг, Люк!
Вот источник AbstractStringBuilder
Ответ 3
String
является неизменным. Добавление строки может только генерировать новую строку.
StringBuilder
является изменяемым. Добавление к StringBuilder
- это операция на месте, например добавление в ArrayList.
Ответ 4
Это не компилируется.
String S= "orange";
S.append("apple");
если вы делаете
final String S= "orange";
final S2 = S + "apple";
Это не создает никаких объектов, поскольку во время компиляции он оптимизируется до двух строковых литералов.
StringBuilder s = new StringBuilder("Orange");
s.append("apple");
Это создает два объекта StringBuilder
и char[]
, которые он обертывает. Если вы используете
String s2 = s.toString();
Это создает еще два объекта.
Если вы делаете
String S= "orange";
S2 = S + "apple";
Это то же самое, что и
String S2 = new StringBuilder("orange").append("apple").toString();
который создает 2 + 2 = 4 объекта.
Ответ 5
StringBuffer, как и StringBuilder, выделяет массив char, в который он копирует строки, которые вы добавляете. Он создает только новые объекты, когда количество символов превышает размер массива, и в этом случае он перераспределяет и копирует массив.
Ответ 6
String s = "orange";
s.append("apple");
Это неверно, потому что метод append недоступен в String:
Ответ 7
StringBuilder
хранит буфер char
в char[]
и преобразует их в String
, когда вызывается toString
.
Ответ 8
tl; dr: В простых словах каждое выражение конкатенации строки с использованием символа +
приводит к новому объекту String
, при этом содержимое исходных строк копируется в новое. StringBuffer
содержит внутреннюю структуру, которая расширяется только тогда, когда это необходимо, что к ней добавляются символы.
Эй, но многие люди используют конкатенацию +
!
Ну, мы/они не должны.
В терминах использования памяти вы используете массив в StringBuffer
для хранения символов - это изменение размера, правда, но редко, если алгоритм, применяемый при изменении размера, эффективен, и только один объект String
, который созданный после вызова toString()
, намного лучше, чем создание нового объекта String
при каждом конкатенации +
.
В терминах временной сложности символы копируются только один раз из _chars
в новую строку (O(n)
временная сложность), которая в общем случае должна быть лучше, чем конкатенация строк с помощью оператора +
, на котором каждая операция приводит к новой копии символов для нового объекта, что приводит к операциям O(1 + 2 + .... + n) = O(n^2)
.
Должен ли я реализовать его самостоятельно?
Это было бы хорошо для вас с точки зрения упражнений, но современные языки предоставляют собственные реализации StringBuffer
для использования в производственном коде.
В четырех простых шагах:
Ответ 9
Как описано выше, StringBuffer
является изменяемым и реализуется с использованием массива char
. Операции в StringBuffer
выполняются на месте.
Дополнительная информация доступна по следующей ссылке
http://www.concentric.net/~ttwang/tech/jfastbuf.htm
Он показывает простые реализации StringBuffer, используя массив char
.
Ответ 10
****String s1="Azad"; ----One object will create in String cons. pool
System.out.println(s1);--output--Azad
s1=s1.concat("Raja"); Two object will create 1-Raja,2-AzadRaja and address of AzadRaja Store in reference s1 and cancel ref.of Azad object
System.out.println(s1); --output AzadRaja****