Java文字列クラスのパフォーマンスが実際にどのように異なるのか疑問に思ったことはありませんか?
このトピックでは、String、StringBuilder、StringBufferクラスのjava.langクラスのパフォーマンスを比較しました。
明らかな事実
Javaには、文字列を操作するための3つの主要なクラスがあるのは秘密ではありません。 プログラムで最も頻繁に使用するメインクラスは
Stringです。 このクラスの特徴は、不変の文字列を作成することです。 つまり オブジェクトを作成するときに初期化した文字列は、そのまま残ります。 したがって、設計:
String st = "";
st += "";
文字列「MashaSasha」を含む新しいオブジェクトが作成され、元のオブジェクトはガベージコレクターによって破棄されます。
同じ文字列オブジェクトに多数の連結操作がある場合、これは新しいオブジェクトを生成する集中的なプロセスにつながり、ガベージコレクターに作業を追加します。
可変文字列が必要な場合、開発者は他のクラスを提供します。 もともとJavaであった最初のものは、
StringBufferと新しいStringBuilder(バージョン1.5以降に導入されました)でした。 ドキュメントにある
ように 、
StringBufferはマルチスレッドアプリケーションで安全に使用できますが、2番目の方が効率的です。
何が欲しい?
まあ、もっと効果的で、あまり効果的ではない、これは確かに良いが、数字が欲しい。 結局のところ、別のプログラマが考えるかもしれませんが、数ミリ秒を節約するために、このような素晴らしい文字列の代わりに「不便な」StringBuffer / StringBuilderを使用する価値はありますか? 他の人は、たとえば10万の連結を実行する必要がある状況はないと言うでしょう...しかし、奇妙なことに、大きな違いはありますか?
テスト
テキストファイル「onegin.txt」から行を読み取ります(クラシックを支援するために呼び出します)。 ファイルのサイズは297463バイト、utf-8、27195ワードです。 3つのクラスすべてを使用して、ファイルのすべての単語を1行に配置して、パフォーマンスを比較しましょう。 より興味深いものにするために、異なるJVMと2つのOSでテストしてみましょう。 Linux(LinuxMint 9を使用しているのは、誰も知らない人にとってはこのような華やかなUbuntuです)とWin XP Pro SP3です。 私はAtom N280でネットブックから書いているので、両方のOSは32ビットです。 しかし、私たちは記録を立てません。トレンドは私たちにとって重要です。
実際にはプログラム自体、どこも簡単ではありません:
package stringtest1;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
public class Main {
public static void main( String [] args) throws FileNotFoundException, IOException {
BufferedReader reader = new BufferedReader( new FileReader( "onegin.txt" ));
StringBuilder sb = new StringBuilder ();
String line = null ;
while ( (line = reader.readLine()) != null ) {
sb.append(line).append( "\n" );
}
reader.close();
String [] words = sb.toString().split( "\\s+" );
System. out .println( "Total words:" + words.length);
waitEnter();
long ts = System.nanoTime();
String buff = "" ;
//2 StringBuffer buff = new StringBuffer();
//3 StringBuilder buff = new StringBuilder();
for ( String word : words) {
buff += word + " " ;
//2&3 buff.append(word).append(" ");
}
long te =System.nanoTime();
System. out .println( "Complete, lenght:" + buff.length() + " elapsed time:" + (te - ts)/1e6 + "ms" );
}
private static void waitEnter() {
Scanner scan = new Scanner(System. in );
System. out .print( "Press Enter key." );
scan.nextLine();
}
}
* This source code was highlighted with Source Code Highlighter .
StringBufferとStringBuilderのオプションは似ており、コメントに表示されます。
各仮想マシンの各オプションの動作時間の測定を5回行い、平均値を計算しました。
結果
Linux
クラス | JDK 1.6.0_18を開きます | HotSpot 1.6.0_20 | JRockit 4.0.1 |
---|
ひも | 27390ms | 26850ms | 26940ms |
StringBuffer | 35.55ms | 34.87ms | 15.41ms |
StringBuilder | 33.01ms | 31.78ms | 12.82ms |
Windows XP
クラス | HotSpot 1.6.0_20 | JRockit 4.0.1 |
---|
ひも | 55260ms | 45330ms |
StringBuffer | 19.38ms | 14.50ms |
StringBuilder | 16.83ms | 12.76ms |
結論
変更可能な文字列が必要な場合は、(マルチスレッドアプリケーションの)StringBufferと残りのStringBuilderを使用します。 違いは非常に顕著です。
Open JDKのJVMがやや遅れているのは明らかです。Sunが存在するか、すでにOracleがねじれています。 LinuxとWinXPでStringクラスのオブジェクトを操作するのになぜそんなに大きな違いがあるのかは完全には明らかではありません。 Tolley Winでは、JVMをLinuxほど効率的に動作させることはできませんか、それともJVM実装の機能です...ここでさらに掘り下げる必要があります。
参照用:
JRockitはOracleの仮想マシンです。
HotSpotは、もともとSunが開発したマシンで、現在はOracleが単独で購入しています。
オープンJDK-Sunが一度にオープンしたソースコードに基づいたオープンソースJDK。