Javaでゼロ埋めやスペース埋めを行う際の最適解
はじめに
本記事では Java で文字列をゼロやスペースで埋めるいくつか方法を、実行速度とあわせて紹介します。
記事の最後で、どの方法を用いるのが良いのかをまとめています。
String.format を使用する
String
クラスの format()
メソッドを利用することで0埋めやスペース埋めができます。
おそらく最もオーソドックスな方法です。「java 0埋め」で検索した時にも一番引っかかる手法だと思います。
標準ライブラリで実装できるうえ、1行のコーディングで済みますので、容易に処理を実装できるという利点がありますが、実行速度が遅いという欠点があります。
以下は8桁に満たない数値に対して0を付与する処理の例です。
int target = 1;
String result = String.format("%08d", target);
System.out.println(result); // 00000001
"%08d"
の中の「0」が埋める文字、「8」が桁数を意味します。そのため0ではなく半角スペースを埋めたい場合には、引数を "% 8d"
とします。詳細については公式ドキュメントを参照してください。
問題は実行速度です。 String.format()
を100万回実行した時の所要時間は 1450 ミリ秒でした。
int target = 1;
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1_000_000; i++) {
String result = String.format("%08d", target);
}
long endTime = System.currentTimeMillis();
long diff = endTime - startTime;
System.out.println("time: " + diff + "ms"); // time: 1450ms
String.format()
以外の0埋め(スペース埋め)の方法を後述しますが、すべての方法の中で最も処理速度が遅いのは String.format()
です。
速い処理が求められるケースでは String.format()
の使用は避けた方が良いでしょう。
Apache Commons Lang を利用する
サードパーティ製ライブラリ Apache Commons Lang にも文字埋めをサポートするメソッドが用意されています。
以下も前述の例と同じく、8桁に満たない数値に対して0を付与する処理の例です。
import org.apache.commons.lang3.StringUtils;
// ...省略...
String target = "1";
String result = StringUtils.leftPad(target, 8, '0');
System.out.println(result); // 00000001
StringUtils.leftPad()
を使うことで0埋めやスペース埋めができます。
実行速度も十分な速さです。 StringUtils.leftPad()
を100万回実行した時の所要時間は 59 ミリ秒でした。
import org.apache.commons.lang3.StringUtils;
// ...省略...
String target = "1";
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1_000_000; i++) {
String result = StringUtils.leftPad(target, 8, '0');
}
long endTime = System.currentTimeMillis();
long diff = endTime - startTime;
System.out.println("time: " + diff + "ms"); // time: 59ms
最初に紹介した String.format()
よりも10倍以上速く処理できています。 Apache Commons Lang を利用しているプロジェクトであれば、 String.format()
ではなく、 Apache Commons Lang の StringUtils.leftPad()
を利用することをお勧めします。
Google Guava を利用する
サードパーティ製ライブラリ Google Guava にも同様に文字埋めをサポートするメソッドが用意されています。
8桁に満たない数値に対して0を付与する処理の例は以下の通りです。
import com.google.common.base.Strings;
// ...省略...
String target = "1";
String result = Strings.padStart(target, 8, '0');
System.out.println(result); // 00000001
Strings.padStart()
を使うことで0埋めやスペース埋めができます。
実行速度も十分な速さです。私が検証する限りでは Apache Commons Lang の StringUtils.leftPad()
を使う場合とほとんど変わらない速度でした。
import com.google.common.base.Strings;
// ...省略...
String target = "1";
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1_000_000; i++) {
String result = Strings.padStart(target, 8, '0');
}
long endTime = System.currentTimeMillis();
long diff = endTime - startTime;
System.out.println("time: " + diff + "ms"); // time: 77ms
先と同様、 Google Guava を利用しているプロジェクトであれば、 String.format()
ではなく、 Google Guava のメソッドを利用することをお勧めします。
独自メソッドを作成する
Apache Commons Lang や Google Guava のようなサードパーティ製ライブラリを利用することはできないが String.format()
の速度には満足できない、あるいは独自の文字埋め処理を行いたい場合には専用のメソッドを作成しましょう。
汎用的な文字埋めメソッドを作成してみました。
public static String padLeft(String target, int length, char padChar) {
int targetLength = target.length();
if (targetLength >= length) {
return target;
}
StringBuilder sb = new StringBuilder(length);
for (int i = targetLength; i < length; i++) {
sb.append(padChar);
}
sb.append(target);
return sb.toString();
}
- Apache Commons Lang の
StringUtils.leftPad()
、 Google GuavaStrings.padStart()
と同様の引数にしています。第一引数が文字を埋める対象の文字列、第二引数が桁数、第三引数が埋める文字です。
このメソッドを使用して0埋めを行う場合、以下のような処理になります。
String target = "1";
String result = padLeft(target, 8, '0');
System.out.println(result); // 00000001
前述の文字埋めメソッドの内部では、 StringBuilder
を用いて文字を結合する処理を行っているため、処理速度は問題ありません。私が検証する限りでは Apache Commons Lang の StringUtils.leftPad()
を使う場合とほとんど変わらない速度でした。
String target = "1";
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1_000_000; i++) {
String result = padStart(target, 8, '0');
}
long endTime = System.currentTimeMillis();
long diff = endTime - startTime;
System.out.println("time: " + diff + "ms"); // time: 76ms
まとめ
0埋めやスペース埋めを行う方法はいくつかありますが、実行速度の面から String.format()
は避けた方が良いです。
サードパーティ製ライブラリの Apache Commons Lang や Google Guava を利用できるのであればそれを使いましょう。
それが難しければ文字埋めメソッドを作成して、そのメソッドを呼び出すようにしましょう。
Discussion