Java: String型の足し算は遅い?


確認

JavaではString型の足し算が遅いようです。(もしかしたらJavaに限らないことかも知れません)
Stringの内容が大きくなれば大きくなるほど遅くなります。

例えばテキストファイルからデータを読み出して一部を少し変えてまたファイルに書き戻したいとします。
そのためには一度変数にファイルのデータをすべて読み出す必要があります。
Stringの足し算を使うと以下のような感じになるでしょう。

import java.io.*;

public class StrTest1 {
	public static void main(String[] args) {
		StrTest1 st = new StrTest1();
	}

	public StrTest1() {
		String filedata = "", l;
		BufferedReader br;
		BufferedWriter bw;

		try {
			br = new BufferedReader(new FileReader("test.txt"));
			while ((l = br.readLine()) != null) {
				// ここで必要に応じてlをちょこっと変える
				filedata += l + "\n";
			}
			br.close();
			bw = new BufferedWriter(new FileWriter("test.txt"));
			bw.write(filedata);
			bw.flush();
			bw.close();
		} catch(IOException e) {
			e.printStackTrace();
		}
	}
}

改善

これを改善するには一つの変数に結合していくのではなく、配列を使った方が良いようです。
例えば以下のようにします。

import java.io.*;

public class StrTest2 {
	public static void main(String[] args) {
		StrTest2 st = new StrTest2();
	}

	public StrTest2() {
		String[] filedata;
		String l;
		int linenum = 0;
		BufferedReader br;
		BufferedWriter bw;

		try {
			br = new BufferedReader(new FileReader("test.txt"));
			while ((l = br.readLine()) != null) {
				linenum++;
			}
			br.close();
			br = new BufferedReader(new FileReader("test.txt"));
			filedata = new String[linenum];
			for (int i = 0; i < linenum; i++) {
				filedata[i] = br.readLine();
				// ここで必要に応じてfiledata[i]をちょこっと変える
			}
			br.close();
			bw = new BufferedWriter(new FileWriter("test.txt"));
			for (int i = 0; i < linenum; i++) {
				bw.write(filedata[i]);
				bw.newLine();
			}
			bw.flush();
			bw.close();
		} catch(IOException e) {
			e.printStackTrace();
		}
	}
}

こちらの方がファイルを2回読むことになりますが、実際に(100KB程度のテキストファイルを用意して)実行してみると速いことが分かります。

また、最初の例では改行を"\n"で付け加えていますが、Javaでファイルに改行を入れたいときはメソッドnewLine()を使うべきです。
これによって、(文字コードに対応した)適切な改行コードを入れることが出来ます。



miniminisoftトップへ
THLAND ホームへ