java.lang.Stringにはformatメソッドが定義されている。
数値の0埋め、3桁区切り、日付の整形など、指定した形式にフォーマットする事に関してはかなり便利なメソッドである。
しかし、Androidプログラミングでこれを使用する場合は要注意。String.formatは内部でFormatterオブジェクトを生成している為かなり遅い。
例えば数値の0埋めなどは、以下のようにStringBuilderを使用して愚直に0を連結すると約6倍高速に動作する。
StringBuilderをnewせずに使いまわすテクニックを利用している事に注意。使いまわさないと速度が約半分になる。それでも十分速いが。
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// String.formatを使用して100000回試行.
long timeMillis = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
String.format("%06d", i);
}
// かかったミリ秒を出力するイディオム. 前の時間 - (次の時間比較の為に代入しつつ現在の時間)、の全体をマイナスに. 式が左から評価される為.
System.out.println(- (timeMillis - (timeMillis = System.currentTimeMillis())));
// 愚直な文字列連結での100000回試行.
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++) {
// StringBuilderの中身を空にする.
sb.setLength(0);
sb.append(i);
for (int j = 6, size = sb.length(); j > size; j--) {
sb.insert(0, "0");
}
// これが無ければ約30倍高速に動作するが, 結果をStringに合わせる為仕方ない.
sb.toString();
}
System.out.println(- (timeMillis - (timeMillis = System.currentTimeMillis())));
}
}
05-08 13:10:13.250: I/System.out(18793): 6575
05-08 13:10:14.331: I/System.out(18793): 1084
日付フォーマットの例。android.text.format.Timeが使用できる状況であれば、下記のように15倍ほど高速に動作する。
使えない状況であったとしても、SimpleDateFormatをループ外でnewし、適宜formatした方が高速に動作する。
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Date date = new Date();
long timeMillis = System.currentTimeMillis();
// String.formatを使用して10000回試行.
String formatStr = "%1$tY%1$tm%1$td";
for (int i = 0; i < 10000; i++) {
String.format(formatStr, date);
}
System.out.println(- (timeMillis - (timeMillis = System.currentTimeMillis())));
// SimpleDateFormatを使用して10000回試行.
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
for (int i = 0; i < 10000; i++) {
sdf.format(date);
}
System.out.println(- (timeMillis - (timeMillis = System.currentTimeMillis())));
// android.text.format.Timeを使用して10000回試行.
Time time = new Time();
time.set(date.getTime());
formatStr = "%Y%m%d";
for (int i = 0; i < 10000; i++) {
time.format(formatStr);
}
System.out.println(- (timeMillis - (timeMillis = System.currentTimeMillis())));
}
}
05-08 13:40:49.091: I/System.out(19604): 2948
05-08 13:40:50.322: I/System.out(19604): 1230
05-08 13:40:50.502: I/System.out(19604): 186
業務では目に見えてこのようなループ処理が行われている事が少ないが、メソッド内でString.formatを使用しており、それが暗に何百回も呼ばれている、という事がままある。
0 件のコメント:
コメントを投稿