java.lang.AbstractStringBuilder.Вся базовая логика по изменению строк в
StringBuilder /
StringBuffer лежит в одном базовом классе:
abstract class AbstractStringBuilder implements ... {
// изменяемый массив байтов
byte[] value;
// если символы хранятся одним байтом (LATIN1) то coder равен нулю, если двумя (UTF16) coder равен 1
byte coder;
// количество символов, а не байтов: один символ может хранится двумя байтами (кириллица в UTF16)
int count;
...
}
Добавление новых символов похоже на добавление новых значений в
ArrayList, также при заполнении текущего массива создается новый:
public AbstractStringBuilder append(String str) {
if (str == null) {
return appendNull();
}
int len = str.length();
// если в массиве не хватает места для новой строки создается новый
ensureCapacityInternal(count + len);
putStringAt(count, str);
// count это количество символов, не байт!
count += len;
return this;
}
private void ensureCapacityInternal(
int minimumCapacity
) {
// так определяется количество символов в массиве, если на символ приходится 1 байт, то coder == 0, длина вернется как есть, а если на символ приходится 2 байта, то coder == 1, тогда произойдет сдвиг вправо на единицу, а это деление на 2
int oldCapacity = value.length >> coder;
// если для новых символов нет места создаем новый массив
if (minimumCapacity - oldCapacity > 0) {
// создает копию массива с большим размером
value = Arrays.copyOf(
value,
// newCapacity() вернет новый размер массива в символах, а нам нужно в байтах, поэтому добавляется coder, при coder == 0 ничего не произойдет, так как каждый символ это один байт, а при coder == 1 произойдет сдвиг влево на 1, а это умножение на 2
newCapacity(minimumCapacity) << coder
);
}
}
Метод
newCapacity() либо возвращает минимально необходимый размер либо размер в 2 раза больший текущего размера, в
ArrayList кстати используется коэффициент в 1.5 раза.
Добавление строки через
append() метод это самая обычная вставка байтов строки в массив байтов
AbstractStringBuilder:
// чуток упростил метод
private void putStringAt(
// index == count, то есть вставка в конец
int index,
String str
) {
// если строка пришла в UTF16 надо расширить текущий массив до 2 байтов на 1 символ
if (getCoder() != str.coder()) {
inflate();
}
// байты строки копируются в текущий массив байтов
str.getBytes(
value, 0,
index, coder, str.length()
);
}
Для строк не такая интересная логика как для чисел, но обо этом в другой раз.
P.S. Урок по
LinkedList уже на подходе
https://androidunderthehood.ru/courses/kotlin-jvm-data-structures