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

# 概要
[Apache Commons](http://commons.apache.org/)の[Commons Lang](http://commons.apache.org/proper/commons-lang/)の`StringUtils`のsplit系メソッドはバリエーションがたくさんあるが、一部違いが分かりづらいものもあり、[APIドキュメント](http://commons.apache.org/proper/commons-lang/javadocs/api-3.7/index.html)の説明や例を読んでも、ネットの情報を検索してもイマイチよく分からなかったので、違いを確認してみた。

# 使用バージョン
現時点での最新の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.と異なる。
一見、文字列のセパレータが使えそうに見えるが、あくまでも**セパレータは１文字**でそれが複数種類指定できる、という分かりづらい仕様。さらに、型がStringのため勘違いしやすく、また、隣接するセパレータは１つのセパレータとして扱われる仕様のため、あたかも文字列でセパレートできたかのように見える場合が多く、その後たまにうまくいかないケースに遭遇したりするとハマるので注意。
例えば、

```java:
StringUtils.split("xxxxxandyyyyyandzzzzz", "and");
```
の場合は、

```java:
{"xxxxx", "yyyyy", "zzzzz"}
```
が返ってくるので、「お！ちゃんと`and`でsplitできてるな。よしよし！」と思ってしまうが、

```java:
StringUtils.split("xxaxxandyynyyandzzdzz", "and");
```
の場合は、

```java:
{"xxaxx", "yynyy", "zzdzz"}
```
が返ってくると思いきや、実際には結果は

```java:
{"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`で分割する。これが文字列でセパレートしたい時に使うメソッド。
これであれば、

```java:
StringUtils.splitByWholeSeparator("xxaxxandyynyyandzzdzz", "and");
```
の場合もちゃんと、

```java:
{"xxaxx", "yynyy", "zzdzz"}
```
が返ってくる。

### 2-2. splitByWholeSeparator(String str, String separator, int max)
2-1.に加え、分割上限数`max`が指定できるバージョン。

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

```java:
StringUtils.split("a  b");
```
の場合は、

```java:
{"a", "b"}
```
が返るが、

```java:
StringUtils.splitPreserveAllTokens("a  b");
```
の場合は、

```java:
{"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)
文字のタイプを判定し、連続する同じタイプの文字群を１つのトークンとして分割するという、ちょっと毛色の変わったsplitメソッド。文字のタイプ判定は`java.lang.Character`の[getType()](https://docs.oracle.com/javase/jp/10/docs/api/java/lang/Character.html#getType(int))にて行われる。このgetType()メソッドのAPIドキュメントの関連項目の覧にそのカテゴリ分けが書いてあるが、めっちゃ種類が多い！

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

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

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