今まで、まったく気にせずにきたんですが...あっ、どうもボクです。
Javaで、StringBuilder と、StringBuffer ってあるのは知ってたんだけど、どっちを使うべきかってあんまり意識してこなかったんですが。
というわけで、今回もJavaで。
スレッドセーフかスレッドセーフでないか
ズバリ、そういうことらしいっす。
- AbstractStringBuilderクラス : 実際の実装を持つ親クラス
- StringBuilderクラス : スレッドセーフでないサブクラス
- StringBufferクラス : スレッドセーフなサブクラス
【Java】StringBuilderとStringBufferの違いをスレッドセーフの観点で検証してみた - カタカタブログ
メソッドの違いはというと、
StringBuilderのappendメソッド
StringBufferのappendメソッド
【Java】StringBuilderとStringBufferの違いをスレッドセーフの観点で検証してみた - カタカタブログ
【Java】StringBuilderとStringBufferの違いをスレッドセーフの観点で検証してみた - カタカタブログ
【Java】StringBuilderとStringBufferの違いをスレッドセーフの観点で検証してみた - カタカタブログ
⇧ StringBuffer は、マルチスレッドに対応してる分、処理速度が落ちるらしいとのこと。
StringBuffer クラスのすべてのメソッドは synchronized になっており、同期化されています。このため、複数のスレッドから使用される場合でも、安全に使用することができます。
その一方で同期化にはコストがかかります。簡単にいえばメソッドを synchronized にすると遅くなってしまうのです。
しかし、StringBuffer を使うときに本当にスレッドセーフが必要ですか?
私が書いてきたコードには StringBuffer クラスにスレッドセーフが必要だったケースはほとんどありませんでした。それなのにわざわざ同期化した StringBuffer クラスを 使う必要はありません。
そこで、登場したのがスレッドセーフではない StringBuilder クラスです。
⇧ 上記サイト様によりますと、StringBuilder 使っとけば大丈夫ってことらしいっす。
いままで、StringBuffer のほうが、処理が速いんだと思ってました(涙)。
というわけで、StringBuilder
Aizu Online Judge のStringに関する問題でトライ。
Eclipseで、適当なJavaプロジェクト、クラスを作成で。
こんな感じのコーディングになりました。
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; public class Transformation { public static void main(String[] args) { // TODO 自動生成されたメソッド・スタブ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); List<string> list = new ArrayList<>(); try { // 対象の文字列 StringBuilder bl = new StringBuilder(br.readLine()); // 命令の回数 int q = Integer.parseInt(br.readLine()); for (int i = 0; i < q; i++) { // 命令(文字列の編集内容) String[] order = br.readLine().split("\\s"); // 文字列を編集する開始位置 int a = Integer.parseInt(order[1]); // 文字列を編集する終了位置 int b = Integer.parseInt(order[2]) +1; if (order[0] != null) { switch (order[0]) { case "print" : // a 文字目から b 文字目までを出力する。 list.add(bl.substring(a, b).toString()); // 出力する内容をリストに保存 break; case "reverse" : // a 文字目から b 文字目までを逆順にする。 bl.replace(a, b, (new StringBuilder(bl.substring(a, b)).reverse()).toString()); break; case "replace" : // a 文字目から b 文字目までを、指定した文字列で置き換える。 bl.replace(a, b, order[3]); break; default : break; } } } // 結果を出力 for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } } catch (IOException e) { // TODO 自動生成された catch ブロック e.printStackTrace(); } } }
そしたら、実行で。
入力する内容は、
Input
1 行目に文字列 が与えられます。 は英小文字のみ含みます。2 行目に命令の数 が与えられます。続く 行に各命令が上記の形式で与えられます。
ということで、
う~ん、StringBuffer、StringBuilder のどっちを使うかで迷った時は、よっぽどのことが無い限りは、StringBuilder を使っておけば良いらしいですね。
ちなみに、JavaのStringBuilderの内容をリセットするには、
⇧ length に、0 を設定してあげれば良いとのこと。
今回はこのへんで。