3

次のコードでは...

StringBuffer buf = new StringBuffer("Is is a far, far better thing that i do");
System.out.println("buf = "+ buf);
System.out.println("buf.length() = " + buf.length());
System.out.println("buf.capacity() = " + buf.capacity());

buf.setLength(60);
System.out.println("buf = "+ buf);
System.out.println("buf.length() = " + buf.length());
System.out.println("buf.capacity() = " + buf.capacity());

buf.setLength(30);
System.out.println("buf = "+ buf);
System.out.println("buf.length() = " + buf.length());
System.out.println("buf.capacity() = " + buf.capacity());

...出力は次のとおりです。

buf = Is is a far, far better thing that i do 
buf.length() = 39
buf.capacity() = 55
buf = Is is a far, far better thing that i do
buf.length() = 60
buf.capacity() = 112
buf = Is is a far, far better thing 
buf.length() = 30
buf.capacity() = 112
4

5 に答える 5

2

を呼び出すと、 1setLength(60)ensureCapacity(60)呼び出されます。

ensureCapacity「アレイの倍増」に依存しています。これは、容量を増やす必要があるたびに、(少なくとも)容量が2倍になることを意味します。正確な定義は、JavaDocに記載されていますensureCapacity

容量が少なくとも指定された最小値と等しいことを確認します。現在の容量が引数よりも小さい場合は、新しい内部アレイに大きな容量が割り当てられます。新しい容量は、次のいずれか大きい方です。

  • minimumCapacity引数。
  • 古い容量の2倍、プラス2。

minimumCapacity引数が正でない場合、このメソッドはアクションを実行せず、単に戻ります。

特定のケースでは、2番目の式(太字)が要求された容量よりも大きいため、これが使用されます。2 * 55 + 2は112に等しいので、それが新しい容量になります。

関連する質問:

1)実際には、extendCapacityを呼び出しますが、容量を確保するのと同じように動作します。

于 2012-03-21T10:34:14.153 に答える
2

StringBufferいくつかのポイントでメソッドを呼び出しますexpandCapacity。容量が大きすぎない場合は、sの値を変更するたびに、新しい配列を割り当てる必要がありStringbufferます。つまり、これはある種のパフォーマンスの最適化です。

マニュアルから:

容量を確保する

public void sureCapacity(int minimumCapacity)

容量が少なくとも指定された最小値と等しいことを確認します。現在の容量が引数よりも小さい場合は、新しい内部アレイに大きな容量が割り当てられます。新しい容量は、次のいずれか大きい方です。

* The minimumCapacity argument.
* Twice the old capacity, plus 2. 

minimumCapacity引数が正でない場合、このメソッドはアクションを実行せず、単に戻ります。

パラメータ:minimumCapacity-必要な最小容量。

于 2012-03-21T10:36:57.077 に答える
2

StringBufferが通常どのように使用されるかを検討してください。StringBufferに格納する必要のある文字列が現在の容量を超えると、現在の容量が増加します。アルゴリズムが容量を必要な量まで増やすだけの場合、StringBufferは非常に非効率的です。例えば:

 buf.append(someText);
 buf.append(someMoreText);
 buf.append(Another100Chars);

容量を3回続けて増やす必要がある場合があります。容量を増やすたびに、基になるデータ構造(配列)をメモリに再割り当てする必要があります。これには、ヒープからより多くのRAMを割り当て、既存のデータをコピーし、最終的に以前に割り当てられたメモリをガベージコレクションする必要があります。これが発生する頻度を減らすために、StringBufferは必要に応じて容量を2倍にします。アルゴリズムは、容量をnから2n+2に移動します。このメソッドが実装されているAbstraceStringBuilderのソースコードは次のとおりです。

/**
 * This implements the expansion semantics of ensureCapacity with no
 * size check or synchronization.
 */
void expandCapacity(int minimumCapacity) {
    int newCapacity = value.length * 2 + 2;
    if (newCapacity - minimumCapacity < 0)
        newCapacity = minimumCapacity;
    if (newCapacity < 0) {
        if (minimumCapacity < 0) // overflow
            throw new OutOfMemoryError();
        newCapacity = Integer.MAX_VALUE;
    }
    value = Arrays.copyOf(value, newCapacity);
}

StringBufferに追加するか、setLengthを呼び出すたびに、このメソッドが呼び出されます。

public synchronized void ensureCapacity(int minimumCapacity) {
    if (minimumCapacity > value.length) {
        expandCapacity(minimumCapacity);
    }
}
于 2012-03-21T10:49:49.713 に答える
1

これは「無料マニュアルを読む」場合です。StringBufferのJavadocから-

public StringBuffer(String str)

指定された文字列の内容に初期化された文字列バッファを構築します。文字列バッファの初期容量は、16に文字列引数の長さを加えたものです。

それが最初は55である理由を説明しています。

public void sureCapacity(int minimumCapacity)

容量が少なくとも指定された最小値と等しいことを確認します。現在の容量が引数よりも小さい場合は、新しい内部アレイに大きな容量が割り当てられます。新しい容量は、次のいずれか大きい方です。

•minimumCapacity引数。

•古い容量の2倍、プラス2。

minimumCapacity引数が正でない場合、このメソッドはアクションを実行せず、単に戻ります。

なぜ112に変わるのかを説明します。

于 2012-03-21T10:34:44.467 に答える
0
public synchronized void setLength(int newLength) {
    super.setLength(newLength);
}

スーパーで:

public void setLength(int newLength) {
    if (newLength < 0)
        throw new StringIndexOutOfBoundsException(newLength);
    ensureCapacityInternal(newLength);
....

それで:

private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    if (minimumCapacity - value.length > 0)
        expandCapacity(minimumCapacity);
....

そして最後に:

void expandCapacity(int minimumCapacity) {
    int newCapacity = value.length * 2 + 2;
....
于 2012-03-21T10:35:58.033 に答える