
Java では、mutable 文字列 (変更可能な文字列) を操作する場合、StringBuilder と StringBuffer のどちらかを選択する必要がある場合があります。どちらも値の変更が可能な可変クラスですが、スレッドの安全性、パフォーマンス、アプリケーションの点で大きく異なります。ここでは、それらの特性を比較し、それぞれをいつ使用するかを説明するコード例を示します。
主な違い: StringBuilder と StringBuffer
特徴 |
文字列ビルダー |
文字列バッファ |
可変性 |
変更可能 |
変更可能 |
保存場所 |
ヒープ (文字列プールを使用しません) |
ヒープ (文字列プールを使用しません) |
スレッドの安全性 |
スレッドセーフではありません |
スレッドセーフ |
同期 |
同期されていません |
同期済み |
パフォーマンス |
同期がないため高速化
| 同期オーバーヘッドにより速度が低下
|
使用事例
| シングルスレッドのシナリオ
| スレッドセーフが必要なマルチスレッドのシナリオ
|
各クラスをさらに詳しく見てみましょう。
1. StringBuilder: シングルスレッド環境の効率的な選択
- StringBuilder は
mutable クラスです。つまり、コンテンツの変更が可能です。
スレッド安全ではないため、シングルスレッドのシナリオに最適です。
同期されていません: 同期オーバーヘッドがないため、StringBuilder は StringBuffer より高速です。
マルチスレッドの制限: 追加の安全対策なしでマルチスレッド環境で StringBuilder を使用すると、競合状態やその他の同時実行の問題が発生する可能性があります。
例: StringBuilder でのスレッドの安全性の実証
この例では、2 つのスレッドを使用して文字を StringBuilder インスタンスに追加します。ただし、同期が欠如しているため、
競合状態:が発生します。
パブリック クラス StringBuilderBasics {
public void threadUnsafe() {
// 共有される共通リソース
StringBuilder ビルダー = new StringBuilder();
// スレッドに「A」を 1000 回追加する
スレッド t1 = 新しいスレッド(() -> {
for (int i = 0; i {
for (int i = 0; i public class StringBuilderBasics {
public void threadUnsafe() {
// Common resource being shared
StringBuilder builder = new StringBuilder();
// Thread appending "A" 1000 times
Thread t1 = new Thread(() -> {
for (int i = 0; i {
for (int i = 0; i
説明:
- スレッドの安全性がないため、StringBuilder 出力の最終的な長さは予測できません (例: 2000
ではなく 1840 )。
- これは、両方のスレッドが同時に文字を追加しようとするために発生し、
上書きまたは操作の削除が発生します。
要点: シングルスレッド環境、またはスレッドセーフが外部で処理される場合にのみ StringBuilder を使用してください。
2. StringBuffer: マルチスレッド環境向けの安全なオプション
- StringBuffer は
mutable であり、その内容の変更が可能です。
同期されているため、スレッドセーフになっています。
- スレッド セーフが必要な
マルチスレッド環境に最適です。
パフォーマンス コスト: 同期によりオーバーヘッドが発生するため、StringBuffer は StringBuilder よりも 遅い。
例: StringBuffer のスレッド セーフティ
これは上記と同じ例ですが、今回は StringBuffer:
を使用します。
パブリック クラス StringBufferBasics {
public void threadSafe() {
// 共有される共通リソース
StringBuffer バッファ = new StringBuffer();
// スレッドに「A」を 1000 回追加する
スレッド t1 = 新しいスレッド(() -> {
for (int i = 0; i {
for (int i = 0; i public class StringBuilderBasics {
public void threadUnsafe() {
// Common resource being shared
StringBuilder builder = new StringBuilder();
// Thread appending "A" 1000 times
Thread t1 = new Thread(() -> {
for (int i = 0; i {
for (int i = 0; i
説明:
- StringBuffer は、両方のスレッドが安全に追加されることを保証し、予想される長さの 2000 を達成します。
- 最終的な文字列はスレッドセーフですが、スレッドの実行順序は
非決定的.
要点
: データの一貫性が重要で同期が必要なマルチスレッド アプリケーションには StringBuffer を使用します。
適切なクラスの選択
StringBuilder と StringBuffer のどちらを選択するかを決定するには、次の点を考慮してください:
パフォーマンスが重要でスレッドの安全性が考慮されていない
シングルスレッドのシナリオ- で StringBuilder を使用します。
変更可能な文字列操作が必要で、競合状態を避けるためにスレッドの安全性が必要な マルチスレッド シナリオ- では StringBuffer を使用します。
結論
この比較は、StringBuilder と StringBuffer の間で情報に基づいた選択を行うのに役立ちます。可変性、パフォーマンス、スレッドの安全性のトレードオフを理解すると、Java で文字列を操作する際のより適切な意思決定につながる可能性があります。
関連記事
Java の基礎
アレイ面接の必需品-
Java メモリの基礎-
Java キーワードの基礎-
Java OOP の基礎-
コレクション フレームワークの基本-
- コーディングを楽しんでください!