【Java】String.splitメソッドで想定通りの配列が得られなかった話


はじめに

JavaのString型のメソッドにはsplitメソッドがあります。このメソッドは例えば以下のように用いることで、文字列を任意の文字を境に分割し、分割した要素を持つ配列を生成することができます。

example1.java
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // 配列にしたい文字列
        String str = "リンゴ,ミカン,バナナ,スイカ,メロン";
        // 分割に用いる文字を指定
        String[] strArray = str.split(",");
        for(int i = 0; i < strArray.length; i++) {
            System.out.println((i + 1) + ":" + strArray[i]);
        }
    }
}

このソースを実行すると

1:リンゴ
2:ミカン
3:バナナ
4:スイカ
5:メロン

という結果が得られます。
ではsplitメソッドですが、次の例のように分割に用いる文字が連続していた場合どうなるでしょうか。

example2.java
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // 配列にしたい文字列
        String str = "リンゴ,ミカン,,,";
        // 分割に用いる文字を指定
        String[] strArray = str.split(",");
        for(int i = 0; i < strArray.length; i++) {
            System.out.println((i + 1) + ":" + strArray[i]);
        }
    }
}

このソースを実行すると

1:リンゴ
2:ミカン
3:
4:
5:

という結果が得られると思っていたのですが、そうではなく

1:リンゴ
2:ミカン

と表示されてしまいました。つまりどういうことかというと、example2.javaにおいて得られる配列のサイズが5ではなく、2になってしまうということです。上記の例において、splitメソッドを用いれば配列のサイズが5になるだろうと思っていた私は業務で実際に用いた際に想定通りにならず面喰ってしまいました。

解決策

ではどのようにすれば私の想定通りになったかというと、結論としては以下の例のようにsplitメソッドの第二引数に-1(負の数)を指定します。

example3.java
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // 配列にしたい文字列
        String str = "リンゴ,ミカン,,,";
        // 第二引数に-1を指定
        String[] strArray = str.split(",", -1);
        for(int i = 0; i < strArray.length; i++) {
            System.out.println((i + 1) + ":" + strArray[i]);
        }
    }
}

第二引数に-1を指定することで、

1:リンゴ
2:ミカン
3:
4:
5:

と結果が得られ、カンマで分割した数だけ配列のサイズを得ることができました。

学んだこと

今回の問題を解決するにあたって、公式ドキュメントを読んだ結果、2つのことを学ぶことができました。

1つめはsplitメソッドでは第一引数で指定した文字列で分割するのではなく、正しくは第一引数で指定した正規表現で分割するということです。

てっきり指定した文字列で分割すると思い込んでいた私には目から鱗で、正規表現を駆使すればより複雑な条件で文字列を分割することも可能であるということがわかりました。

2つめは上記の例のように分割したい文字列が連続している場合はsplitメソッドの第二引数に負の数を指定するということです。
splitメソッドの第二引数は分割の閾値を表しています。そして、第二引数を指定していない場合、第二引数に0を指定したことと同じ扱いになり、この場合順番に分割した結果の後続が空文字の場合破棄する仕様になっています。
そのため、example2.javaでは、分割した配列のサイズが5ではなく、2になってしまいました。
これを防ぐためには第二引数に負の数を指定し、分割数を無制限かつ空文字を破棄しないようにする必要があるということがわかりました。

おわりに

今回の問題解決にあたって公式ドキュメントを参照することの大切さを再認識することができました。そして、どういった処理を行っているかをきちんと理解した上でメソッドを用いることの大切さを実感することができました。
この記事が誰かのお役に立てれば幸いです。