Емкость StringBuilder()
Я заметил, что метод capacity
возвращает StringBuilder
емкость без логики
путь... когда-то его значение равно длине строки в другое время, когда оно больше...
есть ли уравнение для знания, которое является его логикой?
Ответы
Ответ 1
При добавлении к StringBuilder
происходит следующая логика:
if (newCount > value.length) {
expandCapacity(newCount);
}
где newCount
- количество требуемых символов, а value.length
- текущий размер буфера.
expandCapacity
просто увеличивает размер поддержки char[]
Метод ensureCapacity()
является общедоступным способом вызова expandCapacity()
, и его документы говорят:
Обеспечивает, чтобы емкость была как минимум равна указанному минимуму. Если текущая емкость меньше аргумента, то новый внутренний массив выделяется с большей пропускной способностью. Новая емкость больше:
- Аргумент minimumCapacity.
- Дважды старая емкость, плюс 2.
Если аргумент minimumCapacity неположителен, этот метод не принимает никаких действий и просто возвращает.
Ответ 2
Я попытаюсь объяснить это с помощью некоторого примера.
public class StringBuilderDemo {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
System.out.println(sb.length());
System.out.println(sb.capacity());
}
}
length()
- длина последовательности символов в построителе
поскольку этот stringbuilder не содержит никакого содержимого, его длина будет равна 0.
capacity()
- количество выделенных пространств символов.
Когда вы пытаетесь построить stringbuilder с пустым содержимым, по умолчанию он принимает размер инициализации как length + 16, который равен 0 + 16. поэтому емкость вернет здесь 16.
Примечание. Емкость, возвращаемая методом capacity(), всегда больше или равна длине (обычно больше) и автоматически расширяется по мере необходимости для дополнения дополнений к построителю строк.
Логика функции емкости:
- Если вы не инициализируете stringbuilder каким-либо контентом, емкость по умолчанию будет принята за 16 символов.
- Если вы инициализируете stringbuilder любым контентом, тогда емкость будет содержать длину + 16.
- Когда вы добавляете новый контент в объект stringbuilder, если текущая емкость недостаточна для получения нового значения, то она будет расти (предыдущая емкость массива + 1) * 2.
Этот анализ берет из фактический код StringBuilder.java
Ответ 3
Эта функция делает что-то другое, чем вы ожидаете, - это дает максимальное количество символов, которые может храниться в памяти экземпляра StringBuilder.
Строковый Builder должен читать
Ответ 4
EDIT: Извинения. Ниже приведена информация о .NET StringBuilder и не имеет строгого отношения к исходному вопросу.
http://johnnycoder.com/blog/2009/01/05/stringbuilder-required-capacity-algorithm/
StringBuilder выделяет пространство для подстрок, которые вы могли бы добавить к нему (так же, как List создает пространство, которое он обертывает). Если вам нужна фактическая длина строки, используйте StringBuilder.Length.
Ответ 5
Из API:
Каждый построитель строк имеет емкость. Пока длина символа последовательность, содержащаяся в строке строитель не превышает емкость, нет необходимости выделять новую внутренний буфер. Если внутренний переполнение буфера, оно автоматически сделал больше.
Всякий раз, когда вы добавляете что-то, есть проверка, чтобы убедиться, что обновленный StringBuilder не будет превышать его емкость, и если это произойдет, внутреннее хранилище StringBuilder будет изменено:
int len = str.length();
int newCount = count + len;
if (newCount > value.length)
expandCapacity(newCount);
Когда к нему добавляются данные, превышающие его емкость, он изменяется в соответствии со следующей формулой:
void expandCapacity(int minimumCapacity) {
int newCapacity = (value.length + 1) * 2;
if (newCapacity < 0) {
newCapacity = Integer.MAX_VALUE;
} else if (minimumCapacity > newCapacity) {
newCapacity = minimumCapacity;
}
value = Arrays.copyOf(value, newCapacity);
}
Дополнительную информацию см. в файле src.zip
, который поставляется вместе с JDK. (Над фрагментами, взятыми из 1.6 JDK)
Ответ 6
Вы можете войти в код JDK и посмотреть, как он работает, он основан на массиве char: new char[capacity]
, он похож на то, как работает ArrayList
(Когда использовать LinkedList над ArrayList?). Оба используют массивы как "эффективные аппаратные средства", трюк состоит в том, чтобы выделить большой кусок памяти и работать в нем до тех пор, пока у вас не закончится память, и для продолжения (развернуть/расти) понадобится следующий большой кусок.