Java split 文字列を分割する方法 - クラス String

Javaのsplitメソッドで文字列を分割する方法です。

Javaでは指定文字列を分割するのにsplitを利用します。他のプログラム言語でもおなじみですよね。プログラミングの基本である文字列操作ですが、ここでは 指定された文字列を分割する方法 をご紹介します。


Javaのsplitとは

Javaのsplit とはどんなメソッドなのか Java API ドキュメント を確認してみましょう。

・Java APIドキュメント

パラメータ: regex - 正規表現の区切り
戻り値: この文字列を指定された正規表現に一致する位置で分割して計算された文字列の配列
説明:
この文字列を、指定された正規表現に一致する位置で分割します。
このメソッドの動作は、2 つの引数を取る split メソッドを、指定された式および引数制限ゼロを指定して呼び出した場合と同じになります。つまり、結果として得られる配列には後続の空の文字列は含まれません。

String (Java Platform SE 6)(java.lang.String)

なるほど、では試してみましょう。

ドット( . ) は、正規表現では、「任意の文字」という特殊な意味を持っています。このまま利用すれると、正しい結果は得られません。 で、エスケープすることで正しい結果が得られます。

以下、ドット( . )区切りのサンプルです。

String sp1 = "saka-en.さかえん.サカエン.";
String[] sps1 = sp1.split("\.");
for ( int i = 0; i < sps1.length; i++ ) {
  System.out.println(sps1[i]);
}

こちらは、タブ区切りのサンプルです。

String sp2 = "saka-en  さかえん  サカエン  ";
String[] sps2 = sp2.split("t");
for ( int i = 0; i < sps2.length; i++ ) {
  System.out.println(sps2[i]);
}

結果は以下の通りです。

saka-en
さかえん
サカエン

API ドキュメントに書かれている「結果として得られる配列には後続の空の文字列は含まれません。」の通り、最後の区切り文字以降(ドットやタブ)は含まれませんでしたね。

Java split しきい値を指定

今度は、しきい値を指定した場合です。

API ドキュメントには以下のように記述があります。

・Java APIドキュメント

パラメータ:
regex - 正規表現の区切り
limit - 結果のしきい値
戻り値: この文字列を指定された正規表現に一致する位置で分割して計算された文字列の配列
説明:
この文字列の各部分文字列を含むメソッドにより返される配列は、指定された式に一致する別の部分文字列、またはその文字列の最後で終了します。
配列内の部分文字列の順序は、この文字列内で出現する順序になります。
入力されたどの部分とも式が一致しない場合、配列は 1 つの要素 (つまり、この文字列) だけを保持します。limit パラメータは、このパターンの適用回数、つまり、結果として得られる配列の長さを制御します。制限 n がゼロより大きい場合、このパターンは n - 1 回以下の回数が適用され、配列の長さは n 次のようになります。 配列の最後のエントリには、最後にマッチした区切り文字以降の入力シーケンスがすべて含まれます。
n が負の値の場合、このパターンの適用回数と配列の長さは制限されません。
n がゼロの場合、このパターンの適用回数と配列の長さは制限されませんが、後続の空の文字列は破棄されます。

なるほど、しきい値 - 1 ってのがミソですね。試してみましょう。

以下のテストを実行すると・・・

String sp3 = "saka-en,さかえん,サカエン";
String[] sps3 = sp3.split(",", 0);
for ( int i = 0; i < sps3.length; i++ ) {
  System.out.println(sps3[i]);
}

結果は以下の通りです。

saka-en
さかえん
サカエン

しきい値に 0 を指定した場合、指定していないのと同じ結果が得られます。

では、しきい値に 0 より大きい値を入れてみるとどうなるのでしょうか?試してみましょう。

以下、しきい値に 1 を指定した場合です。

String sp4 = "JavaJavaJava";
String[] sps4 = sp4.split("a", 1);
for ( int i = 0; i < sps4.length; i++ ) {
  System.out.println(sps4[i]);
}

結果は以下の通りです。

JavaJavaJava

以下、しきい値に 2 を指定した場合です。

String sp5 = "JavaJavaJava";
String[] sps5 = sp5.split("a", 2);
for ( int i = 0; i < sps5.length; i++ ) {
  System.out.println(sps5[i]);
}

結果は以下の通りです。

J
vaJavaJava

以下、しきい値に 3 を指定した場合です。

String sp6 = "JavaJavaJava";
String[] sps6 = sp6.split("a", 3);
for ( int i = 0; i < sps6.length; i++ ) {
  System.out.println(sps6[i]);
}

結果は以下の通りです。

J
v
JavaJava

結果をみると、しきい値 - 1 の回数だけ、分割されているのがわかりますね。

では、しきい値に、マイナス を指定するとどうなるのでしょうか?試してみましょう。

以下、しきい値に -1 を指定した場合です。

String sp7 = "JavaJavaJava";
String[] sps7 = sp7.split("a", -1);
for ( int i = 0; i < sps7.length; i++ ) {
  System.out.println(sps7[i]);
}

結果は以下の通りです。

J
v
J
v
J
v
""(空文字)

以下、しきい値に -2 を指定した場合です。

String sp8 = "JavaJavaJava";
String[] sps8 = sp8.split("a", -2);
for ( int i = 0; i < sps8.length; i++ ) {
  System.out.println(sps8[i]);
}

結果は以下の通りです。

J
v
J
v
J
v
""(空文字)

APIドキュメントに「負の値の場合、このパターンの適用回数と配列の長さは制限されません。」とある通り、特に制限をされない結果が得られましたね。

まとめとサンプルソース

実務で利用するとすれば、システム間のデータのやり取りで、区切り文字を使うケースが多いですね。しきい値を使った分割処理はほとんどしないと思いますが、覚えておいて損はないと思います。

ちなみに対象となる文字列が null の場合、NullPointerException が発生します。都度 try {} catch {} で例外を取得してもいいのですが、ソースが煩雑になるので、以下のようなメソッドを用意して対応する方がトラブルが少ないでしょう。

/**
 * 指定された正規表現に一致する位置で分割します。
 *
 * @param value 処理対象となる文字列
 * @param regex 正規表現の区切り
 * @return 分割後の配列
 */
public static String[] split(String value, String regex) {
  String[] values = new String[0];
  if ( value == null || value.length() == 0 || regex == null || regex.length() == 0 )
    return values;
  return value.split(regex);
}
/**
 * 指定された正規表現に一致する位置で分割します。
 *
 * @param value 処理対象となる文字列
 * @param regex 正規表現の区切り
 * @param limit 結果のしきい値
 * @return 分割後の配列
 */
public static String[] split(String value, String regex, int limit) {
  String[] values = new String[0];
  if ( value == null || value.length() == 0 || regex == null || regex.length() == 0 )
    return values;
  return value.split(regex, limit);
}

処理対象となる文字列が null だったとしても、長さ 0 の配列を返してくれますので、NullPointerException が発生することはありません。後は呼び出し元で、長さ 0 だったら・・・とやって、処理を分岐させましょう。

おつかれさまでした。

この記事がお役に立ちましたら シェア をお願いいたします。