java.util.String#split

1.4で新設されたメソッド。便利な分解メソッドだ。しかし、こいつの挙動にはまった人が結構いる模様。まあ自分もOROとjava.util.regexとで実装切り替えられるWrapper作ったときに、メソッドの互換性試験してて、はじめて気が付いたんだけどさ。
問題となるのは、このsplitメソッドの第二引数limitを指定しない版において、"aa,bb,cc," などのように、最後がデリミタで終わっているケース。"aa","bb","cc","" という、要素数4つの配列が返るかと思いきや、末尾の空文字は削除されてしまうのであった。まあ、実はしっかりと javadoc にも書いてあったんだけど。


http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/lang/String.html#split(java.lang.String)

このメソッドの動作は、2 つの引数を取る split メソッドを、指定された式および引数制限ゼロを指定して呼び出した場合と同じになります。このため、末尾の空文字列は、結果の配列に含まれません。


たとえば、次の式を指定した場合の、文字列「boo:and:foo」の結果を示します。


正規表現 結果
: { "boo", "and", "foo" }
o { "b", "", ":and:f" }


解決策はjavadocのすぐ上にも書いてあるけれど、第二引数 limit に負数を指定して呼び出せばOK。


http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/lang/String.html#split(java.lang.String, int)

limit パラメータは、このパターンの適用回数、つまり、返される配列の長さを制御します。制限 n がゼロより大きい場合、このパターンは n - 1 回以下の回数が適用され、配列の長さは n 以下になります。配列の最後のエントリには、最後にマッチした区切り文字以降の入力シーケンスがすべて含まれます。n が負の値の場合、このパターンの適用回数と配列の長さは制限されません。n がゼロの場合、このパターンの適用回数と配列の長さは制限されませんが、後続の空の文字列は破棄されます。


たとえば、次のパラメータが指定された場合の、文字列「boo:and:foo」の結果を示します。


正規表現 制限 結果
: 2 { "boo", "and:foo" }
: 5 { "boo", "and", "foo" }
: -2 { "boo", "and", "foo" }
o 5 { "b", "", ":and:f", "", "" }
o -2 { "b", "", ":and:f", "", "" }
o 0 { "b", "", ":and:f" }