Как StringBuffer реализует функцию append без создания двух объектов?
Это был вопрос. Меня попросили реализовать StringBuffer
функция append. Я видел код После интервью. Но я не могу понять, как выполняется операция с созданием одного объекта.
Я думаю так.
String s = "orange";
s.append("apple");
здесь создаются два объекта.
но
StringBuilder s = new StringBuilder("Orange");
s.append("apple");
Теперь здесь создается только один объект.
как Java делает эту операцию?
10 ответов
сначала возникает проблема с вашим вопросом:
String s = "orange";
s.append("apple");
здесь создаются два объекта
правильно, создаются два объекта, строка " оранжевый "и строка" яблоко", внутри StringBuffer/StringBuilder никакие объекты не будут созданы, если мы не переполняем буфер. Таким образом, эти строки кода создают 2 или 3 объекта.
StringBuilder s = new StringBuilder("Orange");
s.append("apple");
теперь здесь создается только один объект
Я не знаю где вы это получите, здесь вы создаете один объект StringBuilder, одну" оранжевую "строку, одну" яблочную " строку для в общей сложности 3 объектов или 4, Если мы переполняем буфер StringBuilder. (Я считаю создание массива как создание объекта).
я прочитал Ваш вопрос, как StringBuilder может добавить без создания нового объекта (когда буфер не переполнен)?
вы должны посмотреть StringBuilder
, так как это не потокобезопасная реализация. Код интересно и легко читается. Я добавил встроенные комментарии.
в качестве внутренней структуры существует массив символов, а не строка. Она изначально построена с длиной 16 и будет увеличиваться каждый раз, когда объем. Если строки для добавления подходят в массив char, нет необходимости создавать новые объекты.
StringBuilder
выходит 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's 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
}
строку.метод getchars(int srcBegin, int srcEnd, char[] dst, int dstBegin) копирует символы из этой строки в целевой массив символов.
Итак, метод добавления довольно прост, единственная магия, оставшаяся для обнаружения, - это 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);
}
массивы.copyOf(char [] original, int newLength) копирует указанный массив, усекая или дополняя нулевыми символами (при необходимости), чтобы копия имела указанную длину.
в нашем случае, обивка, так как мы расширяем длину.
String
незыблем. Добавление строки может генерировать только новую строку.
StringBuilder
изменчиво. Добавление к StringBuilder
в месте операции, как добавить в ArrayList.
это не компилируется.
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 объекта.
StringBuffer, как StringBuilder выделяет массив символов, в который он копирует строки, которые вы добавляете. Он создает новые объекты только тогда, когда количество символов превышает размер массива, в этом случае он перераспределяет и копирует массив.
String s = "orange";
s.append("apple");
это неправильно, потому что метод добавления недоступен в строке:
tl; dr: простыми словами, каждая конкатенация строк выражение С помощью +
символ приводит к новому String
объект с содержимым исходных строк, копируемых в новую. StringBuffer
имеет внутреннюю структуру, которая расширяется только при необходимости, что символы добавляются к нему.
Эй, но многие люди используют +
конкатенация строк!
Ну, мы/они не должен.
С точки зрения использования памяти, вы используете массив в StringBuffer
чтобы удерживать символы-это изменяет размер, правда, но редко, если алгоритм, применяемый при изменении размера, эффективен, и только один String
объект, который создается однажды toString()
называется, гораздо лучше, чем создание новой
как другие описывали, StringBuffer
является изменяемым и реализуется с помощью char
массив. Операции в StringBuffer
в месте операции.
еще информация может быть доступна по следующей ссылке http://www.concentric.net / ~ttwang/tech/jfastbuf.htm
он показывает простые реализации StringBuffer с помощью char
массив.
****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****