2012-03-21 5 views
3

...次の例の容量が112になるのはなぜですか。次のコードで

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 

答えて

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); 
    } 
} 
2

setLength(60)の呼び出しがensureCapacity(60)がと呼ばれるようになります。

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

容量が指定された最小値以上であることを確認します。現在の容量が引数よりも小さい場合は、新しい内部配列がより大きい容量で割り当てられます。新しい容量は、次のうち大きい方です。

  • minimumCapacity引数。
  • 二度古い容量、プラス2

minimumCapacity引数が正の値でない場合、このメソッドは何も行わず、単に返します。あなたの特定の場合において

、(太字)は、第2の式は、要求された容量よりも大きい場合、これは使用されます。 2 * 55 + 2は112に等しいので、それが新しい容量になります。

関連質問:

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

1

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

公共のStringBuffer(String str)文字

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

公共ボイドensureCapacity(int型minimumCapacity)

だ理由を説明

は、容量が指定された最小値以上になることを保証します。 現在の容量が引数よりも小さい場合、新しい内部の 配列がより大きな容量で割り当てられます。新しい容量は、 のうち大きい方です。

•minimumCapacity引数。

二度古い容量、プラス2

•minimumCapacity引数が 非正である場合、このメソッドは何も行わず、単に返します。

それはスーパーで112

+0

+1が、私はRTFMはAだと思います厳しい多くのユーザーは、これらのリソースをGoogleにどのように提供しているのかわかりません。 –

+0

-1、我々の誰も私たちが知らなかった人の方へRTFM頭字語を拡大することを夢見ることはないだろう。とにかく、うまくいけば! – halfer

+0

OK、@halfer、私はあなたのフィードバックに沿って細かい編集をしました。すべてのdownvotersはまだこの答えに不満ですか? –

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; 
.... 
2

StringBuffer複数の点でメソッドexpandCapacityを呼び出します。容量をオーバーサイズしない場合は、Stringbufferの値を変更するたびに、新しい配列を割り当てる必要があります。これはパフォーマンスの最適化のようなものです。マニュアルから

ensureCapacity

公共ボイドensureCapacity(INT minimumCapacity)

は、容量が指定された最小値に少なくとも等しいことを保証します。 現在の容量が引数よりも小さい場合、新しい内部の 配列がより大きな容量で割り当てられます。新しい容量が大きい方の です:

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

minimumCapacity引数が正の値でない場合、このメソッドは何も 行動をとらず、単に返します。

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

関連する問題