String vs StringBuffer vs StringBuilder

Javaの中で、Stringは最も広く使用されるクラスの1つです。StringBufferとStringBuilderクラスは文字列を操作するためのメソッドを提供します。StringBufferとStringBuilderの違いについて見ていきます。StringBuffer vs StringBuilderは人気のあるJavaの面接質問です。

String vs StringBuffer vs StringBuilder

文字列は、Javaのコアな面接で最も重要なトピックの一つです。コンソールに何かを出力するプログラムを書いている場合、Stringを使用します。このチュートリアルでは、Stringクラスの主な機能に焦点を当てます。それからStringBufferとStringBuilderクラスを比較します。

JavaのString

  1. Stringクラスは文字列を表します。Stringは2つの方法でインスタンス化することができます。

    String str = "ABC";
    // または
    String str = new String("ABC");
    
  2. JavaではStringは不変です。そのため、マルチスレッド環境で使用するのに適しています。データの不整合の心配がないため、関数間で共有することができます。

  3. ダブルクォーテーションを使用して文字列を作成すると、JVMはまず文字列プール内で同じ値の文字列を探します。見つかれば、プールから文字列オブジェクトの参照を返します。それ以外の場合は、文字列オブジェクトを文字列プールに作成して参照を返します。JVMは異なるスレッドで同じ文字列を使用することで多くのメモリを節約します。

  4. 新しいオペレータを使用して文字列を作成する場合、それはヒープメモリに作成されます。

  5. +演算子は文字列用にオーバーロードされています。これを使用して2つの文字列を連結できます。内部的にはStringBufferを使用してこの操作を行います。

  6. 文字列はequals() と hashCode() メソッドをオーバーライドします。2 つの文字列が等しいのは、文字のシーケンスが同じ場合に限ります。equals() メソッドは大文字と小文字を区別します。大文字と小文字を区別せずにチェックしたい場合は、equalsIgnoreCase() メソッドを使用する必要があります。

  7. 文字列は文字ストリームに対して UTF-16 エンコーディングを使用します。

  8. String は最終クラスです。すべてのフィールドは “private int hash” を除いて最終です。このフィールドには hashCode() 関数の値が含まれます。ハッシュコードの値は、最初に hashCode() メソッドが呼び出されたときにのみ計算され、その後、このフィールドにキャッシュされます。さらに、ハッシュは String クラスの最終フィールドを使用していくつかの計算を行って生成されます。そのため、hashCode() メソッドが呼び出されるたびに、同じ出力が得られます。呼び出し元から見ると、毎回計算が行われているように見えますが、内部的にはハッシュフィールドにキャッシュされています。

String vs StringBuffer

StringはJavaでは不変ですので、連結、部分文字列などのString操作を行うたびに新しいStringが生成され、古いStringはガベージコレクションの対象となります。これらは重い操作であり、ヒープに多くのガベージを生成します。そのため、JavaはString操作に使用すべきStringBufferおよびStringBuilderクラスを提供しています。StringBufferおよびStringBuilderはJavaの可変オブジェクトです。String操作用にappend()、insert()、delete()、substring()メソッドを提供しています。

StringBuffer vs StringBuilder

StringBufferは、Java 1.4までの文字列操作の唯一の選択肢でした。ただし、すべての公開メソッドが同期されているという欠点があります。StringBufferはスレッドセーフを提供しますが、パフォーマンスのコストがかかります。ほとんどのシナリオでは、文字列をマルチスレッド環境で使用しません。そのため、Java 1.5では、スレッドセーフ性と同期以外はStringBufferと似ている新しいクラスStringBuilderが導入されました。StringBufferにはsubstring、length、capacity、trimToSizeなどの追加のメソッドがありますが、これらはStringにも存在するため必要ありません。そのため、これらのメソッドはStringBuilderクラスでは実装されていません。StringBufferはJava 1.0で導入され、StringBufferの欠点を考慮してJava 1.5でStringBuilderクラスが導入されました。シングルスレッド環境にいる場合やスレッドセーフ性に関心がない場合は、StringBuilderを使用するべきです。それ以外の場合は、スレッドセーフな操作にはStringBufferを使用してください。

StringBuilder vs StringBufferのパフォーマンス

I am trying to check the effect on performance because of synchronization with a sample program that performs append() on StringBuffer and StringBuilder object for multiple times.

package com.journaldev.java;

import java.util.GregorianCalendar;

public class TestString {

	public static void main(String[] args) {
		System.gc();
		long start=new GregorianCalendar().getTimeInMillis();
		long startMemory=Runtime.getRuntime().freeMemory();
		StringBuffer sb = new StringBuffer();
		//StringBuilder sb = new StringBuilder();
		for(int i = 0; i<10000000; i++){
			sb.append(":").append(i);
		}
		long end=new GregorianCalendar().getTimeInMillis();
		long endMemory=Runtime.getRuntime().freeMemory();
		System.out.println("Time Taken:"+(end-start));
		System.out.println("Memory used:"+(startMemory-endMemory));
	}
}

I ran the same code for the StringBuffer object also to check the time and memory values. I have executed the code 5 times for each case and then calculated the average values.

Value of i StringBuffer (Time, Memory) StringBuilder (Time, Memory)
10,00,000 808, 149356704 633, 149356704
1,00,00,000 7448, 147783888 6179, 147783888

シングルスレッド環境でもStringBuilderの方がStringBufferよりもパフォーマンスが優れていることが明らかです。このパフォーマンスの違いは、StringBufferのメソッドにおける同期によるものです。

String vs StringBuffer vs StringBuilder

  1. Stringは不変であり、一方でStringBufferとStringBuilderは可変のクラスです。
  2. StringBufferはスレッドセーフで同期されていますが、StringBuilderはそうではありません。そのため、StringBuilderはStringBufferよりも速いです。
  3. 文字列の連結演算子(+)は、内部的にStringBufferまたはStringBuilderクラスを使用しています。
  4. 非マルチスレッド環境での文字列の操作には、StringBuilderを使用すべきです。それ以外の場合はStringBufferクラスを使用してください。

これで、String、StringBuffer、およびStringBuilderの違いについてのクイックな概要が終わります。ほとんどの一般的なプログラミングシナリオでは、StringBuilderがStringBufferよりも適しています。参照:

Source:
https://www.digitalocean.com/community/tutorials/string-vs-stringbuffer-vs-stringbuilder