capacity
メソッドが論理的な方法なしで容量を返すことに気付きましたStringBuilder
...その値が文字列の長さと等しい場合もあれば、それよりも大きい場合もあります...
その論理を知る方程式はありますか?
capacity
メソッドが論理的な方法なしで容量を返すことに気付きましたStringBuilder
...その値が文字列の長さと等しい場合もあれば、それよりも大きい場合もあります...
その論理を知る方程式はありますか?
に追加するとStringBuilder
、次のロジックが発生します。
if (newCount > value.length) {
expandCapacity(newCount);
}
ここnewCount
で、は必要な文字数、value.length
はバッファの現在のサイズです。
expandCapacity
単にバッキングのサイズを大きくしますchar[]
このensureCapacity()
メソッドは、を呼び出すための公的な方法expandCapacity()
であり、そのドキュメントには次のように書かれています。
容量が少なくとも指定された最小値と等しいことを確認します。現在の容量が引数よりも小さい場合は、新しい内部アレイに大きな容量が割り当てられます。新しい容量は、次のいずれか大きい方です。
- minimumCapacity引数。
- 古い容量の2倍、プラス2。
minimumCapacity引数が正でない場合、このメソッドはアクションを実行せず、単に戻ります。
これをいくつかの例で説明しようと思います。
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 を構築しようとすると、デフォルトで初期化サイズは長さ + 16、つまり 0 + 16 になります。したがって、容量はここで 16 を返します。
注: capacity() メソッドによって返される容量は、常に長さ以上 (通常はそれ以上) であり、文字列ビルダーへの追加に対応するために、必要に応じて自動的に拡張されます。
capacity 関数の背後にあるロジック:
この関数は、予想とは異なることを行います。この StringBuilder インスタンスのメモリが現時点で保持できる最大文字数を示します。
編集:お詫び-以下は.NETのStringBuilderに関する情報であり、元の質問と厳密には関連していません。
http://johnnycoder.com/blog/2009/01/05/stringbuilder-required-capacity-algorithm/
StringBuilderは、追加する可能性のあるサブストリングにスペースを割り当てます(Listがラップする配列にスペースを作成するのと同じように)。文字列の実際の長さが必要な場合は、StringBuilder.Lengthを使用します。
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から取得した上記のスニペット)
JDK コード内に移動して、それがどのように機能するかを確認できます。これは char 配列に基づいています:new char[capacity]
の機能に似ていますArrayList
(いつ ArrayList で LinkedList を使用するか? )。どちらも「ハードウェア効率」を高めるために配列を使用します。秘訣は、大きなメモリ チャンクを割り当てて、メモリが不足し、次の大きなチャンクが必要になるまでその中で作業することです (拡張/成長)。
Java 1.8で
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
例えば :
StringBuilder str = new StringBuilder();
System.out.println(str.capacity()); //16
str.append("123456789012345");
System.out.println(str.capacity()); //16
str.append("12345678901234567890");
System.out.println(str.capacity()); // 15 + 20 = 35