概要
StringBuilderとStringBufferは、簡単に混乱する2つの概念です。この記事はソースコードから始まり、2つの類似点と相違点を単純に調べます。
これら2つのうちの1つがスレッドセーフであり、スレッドセーフの1つが非効率的であることを知るのは簡単です。
Java Docの説明
Java Docは、ソースコードを書く人々によって書かれた注釈です。最初にJava Docを見てみましょう。
StringBuilder
文字の可変シーケンス。このクラスは、StringBufferと互換性のあるAPIを提供しますが、同期の保証はありません。このクラスは、ストリングバッファーが単一のスレッドで使用されていた場所で、ストリングバッファーのドロップイン交換として使用するように設計されています(一般的にはそうです)。可能であれば、ほとんどの実装ではより速くなるため、このクラスをStringBufferよりも優先して使用することをお勧めします。
StringBuilderの主要な操作は、あらゆるタイプのデータを受け入れるように過負荷になっている追加および挿入メソッドです。それぞれが特定のデータムを文字列に効果的に変換し、その文字列の文字を文字列ビルダーに追加または挿入します。追加方法は、常にビルダーの端にこれらの文字を追加します。挿入方法は、指定されたポイントに文字を追加します。
たとえば、zが現在の内容が「start」である弦ビルダーオブジェクトを指す場合、メソッドコールz.append( "le")に弦ビルダーが「驚re」を含みますが、Z.insert(4、 "le")は弦ビルダーを変更して「スターレット」を含みます。
一般に、SBがStringBuilderのインスタンスを参照する場合、Sb.Insert(x)はSb.Insert(sb.Length()、x)と同じ効果を持ちます。
すべての弦ビルダーには容量があります。文字列ビルダーに含まれる文字シーケンスの長さが容量を超えない限り、新しい内部バッファを割り当てる必要はありません。内部バッファがオーバーフローすると、自動的に大きくなります。
StringBuilderのインスタンスは、複数のスレッドで使用するのに安全ではありません。そのような同期が必要な場合は、java.lang.stringbufferを使用することをお勧めします。
特に明記しない限り、このクラスのコンストラクターまたはメソッドにヌル引数を渡すと、nullpointerexceptionがスローされます。
以来:
1.5
著者:
マイケル・マクロスキー
参照:
Java.lang.StringBuffer
Java.lang.String
stringbuffer
文字のスレッドセーフ、可変シーケンス。文字列バッファーは文字列のようなものですが、変更できます。いつでも特定の文字のシーケンスが含まれていますが、シーケンスの長さとコンテンツは特定のメソッド呼び出しで変更できます。
文字列バッファーは、複数のスレッドで使用できます。メソッドは、特定のインスタンスのすべての操作が、関係する各スレッドによって行われたメソッド呼び出しの順序と一致するシリアル順序で発生するかのように動作するように、必要に応じて同期されます。
StringBufferの主要な操作は、あらゆるタイプのデータを受け入れるように過負荷になっている追加および挿入メソッドです。それぞれが特定のデータムを文字列に効果的に変換し、その文字列の文字を文字列バッファーに追加または挿入します。追加方法は、常にバッファの最後にこれらの文字を追加します。挿入方法は、指定されたポイントに文字を追加します。
たとえば、zが現在の内容が「start」であるストリングバッファーオブジェクトを指す場合、メソッドコールz.append( "le")に弦バッファーが「驚le」を含みますが、z.insert(4、 "le")は弦バッファーを変更して「スターレット」を含みます。
一般に、SBがStringBufferのインスタンスを紹介する場合、Sb.Append(x)はsb.insert(sb.length()、同じ効果があります。
ソースシーケンス(ソースシーケンスからの追加または挿入など)を含む操作が発生する場合はいつでも、このクラスは、ソースではなく操作を実行する文字列バッファーでのみ同期します。 StringBufferは複数のスレッドから同時に使用できるように設計されていますが、コンストラクターまたは挿入操作がスレッド間で共有されるソースシーケンスに渡される場合、呼び出しコードは、操作の期間中にソースシーケンスの一貫した不変のビューを確保する必要があります。これは、操作の呼び出し中にロックを保持している発信者が、不変のソースシーケンスを使用すること、またはスレッド間でソースシーケンスを共有しないことによって満たされる可能性があります。
すべての文字列バッファには容量があります。文字列バッファーに含まれる文字シーケンスの長さが容量を超えない限り、新しい内部バッファアレイを割り当てる必要はありません。内部バッファがオーバーフローすると、自動的に大きくなります。
特に明記しない限り、このクラスのコンストラクターまたはメソッドにヌル引数を渡すと、nullpointerexceptionがスローされます。
リリースJDK 5の時点で、このクラスには、単一のスレッドであるStringBuilderが使用するために設計された同等のクラスが補完されています。 StringBuilderクラスは通常、同じ操作をすべてサポートするため、これよりも優先して使用する必要がありますが、同期は実行されないため、より速くなります。
以来:
JDK1.0
著者:
アーサー・ヴァン・ホフ
参照:
Java.lang.StringBuilder
Java.lang.String
Javadocの概要
上記から見ることができます:
StringBufferとStringBuilderの両方は、可変文字列と見なすことができます。
StringBufferはスレッドセーフで、最初に表示され、JDK1.0で利用できます。
StringBuilderは非読み取りセーフであり、後で表示され、JDK1.5にのみ存在します。
2つのインターフェイスはまったく同じであり、StringBuilderはより高速です。
実際、これらのポイントを普通に使用するのは良いことですが、ソースコードでどのように実装されているかを見たいと思います。
ソースコード
スレッドの安全を実現する方法
ソースコードから、両方とも抽象クラスの抽象ストリングビルダーを継承していることがわかります
パブリックファイナルクラスStringBuffer拡張抽象ストリングバイユルダーはJava.io.Serializable、CharSequencePublic Final Class StringBuilder Extends AbstractStringBuilder Implements Java.io.Serializable、CharSequence
コードの量はそれほど大きくなく、StringBuilder440行のコード、StringBuffer718行のコード、および最も多くのコードが抽象的なものです。
いくつかの観点から、コードを見て、1つはいくつかの重要な内部構造がどのように見えるか、もう1つは一般的に使用する関数の実装方法です。文字列は不変であるため、一定のプールに配置されます。 stringbuilderとstringbufferは、charアレイを使用して実装する必要があると推測されます。
/***値は文字ストレージに使用されます。 */ char [] value; /***カウントは使用される文字の数です。 */ int count;
データは値で保存され、長さはカウントで表されることがわかります。
いくつかの一般的な方法のさまざまな実装を見てみましょう。
stringbuffer
@Override public Synchronized stringbuffer append(string str){toStringCache = null; super.append(str);これを返します。 } / ** * @Throws StringIndexOutofBoundSexception {@inheritdoc} * / @Override public synchronized stringbuffer insert(int offset、string str){toStringCache = null; super.insert(offset、str);これを返します。 } @Override public synchronized string toString(){if(toStringCache == null){toStringCache = arrays.Copyofrange(value、0、count); } new String(toStringCache、true)を返します。 }StringBuilder
@Override public StringBuilder append(string str){super.append(str);これを返します。 } / ** * @Throws StringIndexOutofBoundSexception {@inheritdoc} * / @Override public StringBuilder Insert(int offset、string str){super.insert(offset、str);これを返します。 } @Override public String toString(){//コピーを作成し、配列を共有しないでください新しい文字列(value、0、count); }コードからわかるように、ほとんどの場合、Strinbbufferは、スレッドの安全性を確保するために同期されたキーワードを追加するだけです。しかし、Tostringメソッドは異なるため、これについては後で説明します。
サイズと成長方法を初期化します
実際には配列であるため、アレイのサイズと成長方法は非常に重要です。コードを見てみましょう。
/** *文字がなく、16文字の初期容量がない文字列バッファーを構築します。 */ public stringbuffer(){super(16); } /** *文字が含まれていない文字列ビルダーと16文字の初期容量を構築します。 */ public stringbuilder(){super(16); }ご覧のとおり、これらのデフォルトコンストラクターは両方とも、デフォルトの配列サイズが16であることを示しています。
なぜ16?理解できませんでした。
成長する方法について心配するのは何ですか?付録の実装を見てみましょう
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;これを返します。 } /** *このメソッドは、EnsureCapacityと同じ契約を結んでいますが、 *は同期しません。 */ private void ensurecapacityinternal(int minimutcapacity){//オーバーフロー - 意識コードif(minimumcapacity -value.length> 0)ExpandCapacity(MinimutCapacity); } /** *これは、 *サイズのチェックまたは同期なしで、surecapacityの拡張セマンティクスを実装します。 */ void endaxCapacity(int minimutcapacity){int newcapacity = value.length * 2 + 2; if(newCapacity -MinimutCapacity <0)newCapacity = MinimutCapacity; if(newcapacity <0){if(minimumcapacity <0)//オーバーフローnew outofmemoryerror(); newcapacity = integer.max_value; } value = arrays.copyof(value、newcapacity); }上記の3つの方法は、容量を拡大する方法を説明しています。
現在の容量 *2+2を置きます
新しく追加された長さがこの値よりも大きい場合、新しく追加された値に設定します
オーバーフローの場合は、OffmemoryErrorを捨ててください
StringBufferでのToStringの実装
/*** toStringによって返される最後の値のキャッシュ。 StringBufferが変更されたときはいつでもクリアされました。 */ private transient char [] toStringcache; @Override public Synchronized stringbuffer append(string str){toStringCache = null; super.append(str);これを返します。 } @Override public synchronized string toString(){if(toStringCache == null){toStringCache = arrays.Copyofrange(value、0、count); } new String(toStringCache、true)を返します。 }ご覧のとおり、アレイToStringCacheが定義されています。データが変更されるたびに、これはnullに設定されます。トストリングするときは、現在のデータからもう一度取ります。
一時的なキーワードは、この配列がシリアル化されないようにすることです。
まとめ
実際、Java自体のソースコードは比較的簡単です。ソースコードから始めることができれば、多くの原則をより深く理解できます。この記事では、いくつかのソースコードをリストし、StringBufferとStringBuilderの類似点と相違点について簡単に説明します。興味のある友達は自分でそれを見ることができます。
上記の記事では、StringBuilderとStringBufferの類似点と違いをソースコードの観点(包括的な分析)から簡単に説明します。私はそれがあなたに参照を与えることができることを願っています、そしてあなたがwulin.comをもっとサポートできることを願っています。