Java
ApacheCommons
Commons-Lang
文字列操作

StringUtilsのsplit系メソッドの違いについて

概要

Apache CommonsCommons LangStringUtilsのsplit系メソッドはバリエーションがたくさんあるが、一部違いが分かりづらいものもあり、APIドキュメントの説明や例を読んでも、ネットの情報を検索してもイマイチよく分からなかったので、違いを確認してみた。

使用バージョン

現時点での最新の3.7

バリエーション

1. split()系

1-1. split(String str)

文字列strをホワイトスペース(タブ、改行、空白)で分割する。空白は全角スペースも認識される。

1-2. split(String str, char separatorChar)

文字列strをセパレータ文字separatorCharで分割する。セパレータを明示的に指定するところが1-1.と異なる。

1-3. split(String str, String separatorChars)

文字列strをセパレータ文字群separatorCharsで分割する。セパレータ文字を複数指定できるところが1-2.と異なる。
一見、文字列のセパレータが使えそうに見えるが、あくまでもセパレータは1文字でそれが複数種類指定できる、という分かりづらい仕様。さらに、型がStringのため勘違いしやすく、また、隣接するセパレータは1つのセパレータとして扱われる仕様のため、あたかも文字列でセパレートできたかのように見える場合が多く、その後たまにうまくいかないケースに遭遇したりするとハマるので注意。
例えば、

StringUtils.split("xxxxxandyyyyyandzzzzz", "and");

の場合は、

{"xxxxx", "yyyyy", "zzzzz"}

が返ってくるので、「お!ちゃんとandでsplitできてるな。よしよし!」と思ってしまうが、

StringUtils.split("xxaxxandyynyyandzzdzz", "and");

の場合は、

{"xxaxx", "yynyy", "zzdzz"}

が返ってくると思いきや、実際には結果は

{"xx", "xx", "yy", "yy", "zz", "zz"}

となり、「はぁ!?」となる。
セパレータに文字列を使いたいときは後述のsplitByWholeSeparator()を使用する。

1-4. split(String str, String separatorChars, int max)

1-3.に加え、最大何個に区切るかをmaxで指定できる。区切れる数がmaxより多くてもmax個以上には区切られない。例えばmaxに2を指定した場合、どんなにたくさん区切れたとしても返ってくる配列の最大要素数は2となる。maxに0やマイナスを指定すると無限個扱いになる。

2. splitByWholeSeparator()系

2-1. splitByWholeSeparator(String str, String separator)

文字列strをセパレータ文字列separatorで分割する。これが文字列でセパレートしたい時に使うメソッド。
これであれば、

StringUtils.splitByWholeSeparator("xxaxxandyynyyandzzdzz", "and");

の場合もちゃんと、

{"xxaxx", "yynyy", "zzdzz"}

が返ってくる。

2-2. splitByWholeSeparator(String str, String separator, int max)

2-1.に加え、分割上限数maxが指定できるバージョン。

3. splitPreserveAllTokens()系

3-1. splitPreserveAllTokens(String str)

今まで出てきたメソッドの場合は隣接するセパレータは1つのセパレータとみなされたが、この系の場合はセパレータが隣接していた場合、空のトークンを返す。
つまり、

StringUtils.split("a  b");

の場合は、

{"a", "b"}

が返るが、

StringUtils.splitPreserveAllTokens("a  b");

の場合は、

{"a", "", "b"}

が返る。

3-2. splitPreserveAllTokens(String str, char separatorChar)

1-2.のPreserveAllTokens版。

3-3. splitPreserveAllTokens(String str, String separatorChars)

1-3.のPreserveAllTokens版。

3-4. splitPreserveAllTokens(String str, String separatorChars, int max)

1-4.のPreserveAllTokens版。

4. splitByWholeSeparatorPreserveAllTokens()系

4-1. splitByWholeSeparatorPreserveAllTokens(String str, String separator)

メソッド名長っ!要は2系と3系の合わせ技で、セパレータに文字列が使え、かつセパレータが隣接した場合は空のトークンを返す。

4-2. splitByWholeSeparatorPreserveAllTokens(String str, String separator, int max)

それのmax指定あり版。見出しがどんどん長くなっていく。ジュゲムジュゲム・・・

5. splitByCharacterType()系

5-1. splitByCharacterType(String str)

文字のタイプを判定し、連続する同じタイプの文字群を1つのトークンとして分割するという、ちょっと毛色の変わったsplitメソッド。文字のタイプ判定はjava.lang.CharactergetType()にて行われる。このgetType()メソッドのAPIドキュメントの関連項目の覧にそのカテゴリ分けが書いてあるが、めっちゃ種類が多い!

StringUtils.splitByCharacterType("ABCabc 123あいう");
実行結果
{"ABC", "abc", " ", "123", "あいう"}

5-2. splitByCharacterTypeCamelCase(String str)

分割ルールは5-1.とほぼ同じで、ただし、英大文字の次に英小文字が来た場合、その英大文字は英小文字側のトークンに属する、というルールだけ異なる。キャメルケース文字列の分割用?

StringUtils.splitByCharacterTypeCamelCase("ABCabc 123あいう");
実行結果
{"AB", "Cabc", " ", "123", "あいう"}