Java には、テキスト データを操作するための 3 つのクラス、String、StringBuffer、StringBuilderがあります。すべての開発者は、言語を学習する最初の段階で最初の言語に遭遇します。残りの2つはどうなるのでしょうか?それらの違いは何ですか?また、どちらのクラスを使用する方が良い場合ですか? 一般に、それらの違いはわずかですが、実際にはすべてを理解することをお勧めします:)
このトピックについては、JavaRush コースの Java マルチスレッド クエストの第 2 レベルで詳しく学ぶことができます。
文字列クラス
このクラスは文字のシーケンスを表します。「This is String」など、プログラムで定義されたすべての文字列リテラルは、String クラスのインスタンスです。 文字列には 2 つの基本的な機能があります。- これは不変クラスです
- これが最後の授業です
final
) を持つことができず、クラスのインスタンスは作成後に変更できません ( immutable
)。これにより、String クラスにいくつかの重要な利点が与えられます。
-
不変性のため、String クラスのインスタンスのハッシュコードはキャッシュされます。オブジェクトのフィールド値は作成後に変更されないため、毎回評価する必要はありません。これにより、このクラスを のキーとして使用すると、高いパフォーマンスが得られます
HashMap
。 -
String クラスは、追加の同期なしでマルチスレッド環境で使用できます。
-
String クラスのもう 1 つの特徴は、
+
Java の " " 演算子をオーバーロードすることです。したがって、文字列の連結 (加算) は非常に簡単です。
public static void main(String[] args) {
String command = "Follow" + " " + "the" + " " + "white" + " " + "rabbit";
System.out.println(command); // Follow the white rabbit
}
内部では、文字列の連結は StringBuilder または StringBuffer クラス (コンパイラーの裁量により) とメソッドappend
(これらのクラスについては後で説明します) によって実行されます。String クラスのインスタンスを他のクラスのインスタンスと追加すると、後者は文字列表現に変換されます。
public static void main(String[] args) {
Boolean b = Boolean.TRUE;
String result = "b is " + b;
System.out.println(result); //b is true
}
toString()
これは String クラスのもう 1 つの興味深いプロパティです。クラス内で定義され、他のすべてのクラスに継承される メソッドを使用して、Object
任意のクラスのオブジェクトを文字列表現にキャストできます。多くの場合、オブジェクトの toString() メソッドは暗黙的に呼び出されます。たとえば、画面に何かを表示したり、別のクラスのオブジェクトに文字列を追加したりする場合です。String クラスにはもう 1 つの機能があります。「asdf」など、Java コードで定義されたすべての文字列リテラルはコンパイル時にキャッシュされ、いわゆる文字列プールに追加されます。次のコードを実行すると:
String a = "Wake up, Neo";
String b = "Wake up, Neo";
System.out.println(a == b);
変数は実際には、コンパイル時に文字列プールに追加された String クラスの同じインスタンスを参照するため、 コンソールではtrue と表示されます。つまり、同じ値を持つクラスの異なるインスタンスは作成されず、メモリが節約されます。 a
b
欠点:
String クラスが主に文字列を操作するために必要であることは推測に難しくありません。ただし、場合によっては、String クラスの上記の機能が利点から欠点に変わる可能性があります。Java コードで文字列が作成されると、多くの場合、その文字列に対して多くの操作が実行されます。- 文字列を別のレジスタに変換します。
- 部分文字列の抽出。
- 連結;
- 等
public static void main(String[] args) {
String s = " Wake up, Neo! ";
s = s.toUpperCase();
s = s.trim();
System.out.println("\"" + s + "\"");
}
一見すると、「起きろ、ネオ!」というセリフをそのまま翻訳したように見えます。大文字に変換するには、この文字列から余分なスペースを削除し、引用符で囲みます。実際、String クラスの不変性により、各操作の結果として、新しい文字列インスタンスが作成され、古い文字列インスタンスが破棄され、大量のガベージが生成されます。メモリの無駄遣いを避けるにはどうすればよいでしょうか?
StringBuffer クラス
String オブジェクトの変更による一時的なガベージの作成を処理するには、StringBuffer クラスを使用できます。これはmutable
クラスです。変更可能。StringBuffer クラスのオブジェクトには特定の文字セットを含めることができ、その長さと値は特定のメソッドを呼び出すことで変更できます。このクラスがどのように機能するかを見てみましょう。新しいオブジェクトを作成するには、次のようなコンストラクターの 1 つを使用します。
- StringBuffer() - 空の(文字のない)オブジェクトを作成します
- StringBuffer(String str) - str 変数に基づいてオブジェクトを作成します (同じシーケンス内の str のすべての文字を含みます)。
StringBuffer sb = new StringBuffer();
StringBuffer sb2 = new StringBuffer("Not empty");
Java の StringBuffer を介した文字列の連結は、 を使用して行われますappend
。一般に、StringBuffer クラスのメソッドは、append
ほぼすべてのデータ型を受け入れることができるようにオーバーロードされます。
public static void main(String[] args) {
StringBuffer sb = new StringBuffer();
sb.append(new Integer(2));
sb.append("; ");
sb.append(false);
sb.append("; ");
sb.append(Arrays.asList(1,2,3));
sb.append("; ");
System.out.println(sb); // 2; false; [1, 2, 3];
}
このメソッドはappend
(他の多くのメソッドと同様に) 呼び出されたオブジェクトを返すため、「チェーン」で呼び出すことができます。上の例は次のように記述できます。
public static void main(String[] args) {
StringBuffer sb = new StringBuffer();
sb.append(new Integer(2))
.append("; ")
.append(false)
.append("; ")
.append(Arrays.asList(1,2,3))
.append("; ");
System.out.println(sb); // 2; false; [1, 2, 3];
}
StringBuffer クラスには、文字列を操作するためのメソッドが多数あります。主なものを列挙してみましょう。
delete(int start, int end)
start
— 位置 から始まり位置 までの文字の部分文字列を削除します。end
deleteCharAt(int index)
— 位置にある文字を削除しますindex
insert(int offset, String str)
str
—位置 に行を挿入しますoffset
。このメソッドinsert
もオーバーロードされており、さまざまな引数を取ることができますreplace(int start, int end, String str)
- すべての文字を次の位置からstart
位置に置き換えます。end
str
reverse()
— すべての文字の順序を逆にしますsubstring(int start, int end)
start
- 位置から位置までの部分文字列を返しますend
substring(int start)
- 位置から始まる部分文字列を返します
start
public static void main(String[] args) {
String numbers = "0123456789";
StringBuffer sb = new StringBuffer(numbers);
System.out.println(sb.substring(3)); // 3456789
System.out.println(sb.substring(4, 8)); // 4567
System.out.println(sb.replace(3, 5, "ABCDE")); // 012ABCDE56789
sb = new StringBuffer(numbers);
System.out.println(sb.reverse()); // 9876543210
sb.reverse(); // Return the original order
sb = new StringBuffer(numbers);
System.out.println(sb.delete(5, 9)); // 012349
System.out.println(sb.deleteCharAt(1)); // 02349
System.out.println(sb.insert(1, "One")); // 0One2349
}
利点:
-
すでに述べたように、StringBuffer は可変クラスであるため、StringBuffer を使用しても、String の場合と同じ量のメモリ ガベージは生成されません。したがって、文字列に対して多くの変更が行われる場合は、 を使用することをお勧めします
StringBuffer
。 -
StringBuffer はスレッドセーフなクラスです。そのメソッドは同期されており、インスタンスは複数のスレッドで同時に使用できます。
欠点:
スレッド セーフはこのクラスの利点である一方で、欠点でもあります。同期メソッドは、非同期メソッドよりも遅くなります。ここで StringBuilder が活躍します。これが StringBuilder という Java クラスの種類、どのようなメソッドがあるのか、どのような機能があるのかを見てみましょう。StringBuilder クラス
Java の StringBuilder は、一連の文字を表すクラスです。スレッド セーフ以外のあらゆる点で StringBuffer に非常に似ています。StringBuilder は、StringBuffer と同様の API を提供します。変数の宣言を StringBufer から StringBuilder に置き換える、よく知られた例を使用してこれを示してみましょう。public static void main(String[] args) {
String numbers = "0123456789";
StringBuilder sb = new StringBuilder(numbers);
System.out.println(sb.substring(3)); //3456789
System.out.println(sb.substring(4, 8)); //4567
System.out.println(sb.replace(3, 5, "ABCDE")); //012ABCDE56789
sb = new StringBuilder(numbers);
System.out.println(sb.reverse()); //9876543210
sb.reverse(); // Return the original order
sb = new StringBuilder(numbers);
System.out.println(sb.delete(5, 9)); //012349
System.out.println(sb.deleteCharAt(1)); //02349
System.out.println(sb.insert(1, "One")); //0One2349
}
唯一の違いは、StringBuffer はスレッド セーフであり、そのすべてのメソッドが同期されるのに対し、StringBuilder はスレッド セーフではないことです。これが唯一の特徴です。Java の StringBuilder は、メソッドが非同期であるため、StringBuffer よりも高速です。したがって、マルチスレッド環境を除いて、ほとんどの場合、Java プログラムには StringBuilder を使用することをお勧めします。3 つのクラスの比較表にすべてをまとめます。
String 対 StringBuffer 対 StringBuilder
弦 | 文字列バッファ | 文字列ビルダー | |
---|---|---|---|
変化しやすさ | Immutable (いいえ) |
mutable (はい) |
mutable (はい) |
拡張性 | final (いいえ) |
final (いいえ) |
final (いいえ) |
スレッドの安全性 | はい、不変性のため | はい、同期のため | いいえ |
いつ使用するか | めったに変更されない文字列を扱う場合 | マルチスレッド環境で頻繁に変更される文字列を扱う場合 | シングルスレッド環境で頻繁に変更される文字列を扱う場合 |
GO TO FULL VERSION