web-dev-qa-db-ja.com

Java String splitが空の値を削除しました

値をセパレータで分割しようとしています。しかし、私は驚くべき結果を見つけています

String data = "5|6|7||8|9||";
String[] split = data.split("\\|");
System.out.println(split.length);

私は8つの値を得ることを期待しています。 [[5,6,7、EMPTY、8,9、EMPTY、EMPTY]しかし私は6つの値しか得られません。

任意のアイデアと修正方法EMPTY値がどこにあっても、それは配列内にあるべきです。

242
Reddy

split(delimiter)はデフォルトで結果配列から末尾の空文字列を削除します。このメカニズムを無効にするには、limitを負の値に設定して、split(delimiter, limit)のオーバーロードバージョンを使用する必要があります。

String[] split = data.split("\\|", -1);

もう少し詳細:
split(regex)は内部的にsplit(regex, 0)の結果を返し、このメソッドの ドキュメント で見つけることができます(強調)

limitパラメーターは、パターンが適用される回数を制御するため、結果として得られる配列の長さに影響します。

制限nより大きいの場合、パターンは最大でn - 1回適用され、配列の長さはn以下になり、配列の最後のエントリには最後のエントリを超えるすべての入力が含まれます。一致した区切り文字。

n正でないの場合、パターンはできるだけ多く適用され、配列は任意の長さにすることができます。

nゼロの場合、パターンはできるだけ多く適用されます。配列の長さは任意で、 )末尾の空の文字列は破棄されます

例外

最後の空の文字列を削除することは意味があることを言及する価値がありますそのような空の文字列が分割メカニズムによって作成された場合のみ"".split(anything)では、""をそれ以上分割できないので、結果として[""]配列になります。
これは分割がここでは行われなかったために起こるので、""は空で末尾はoriginal文字列を表しますが、分割処理ではcreatedではありません.

419
jlordo

String.split(String regex) のドキュメントから:

このメソッドは、与えられた式とlimit引数にゼロを指定して2引数のsplitメソッドを呼び出すのと同じように機能します。 したがって、末尾の空文字列は結果の配列に含まれません。

そのため、2つの引数のバージョン String.split(String regex, int limit) を負の値で使用する必要があります。

String[] split = data.split("\\|",-1);

Doc:

制限nが0より大きい場合、パターンは最大でn - 1回適用され、配列の長さはn以下になり、配列の最後のエントリには、最後に一致した区切り文字を超えるすべての入力が含まれます。 nが正でない場合、パターンはできるだけ多く適用され、配列は任意の長さにすることができます。 nが0の場合、パターンは可能な限り何度も適用され、配列の長さは任意になり、末尾の空の文字列は破棄されます

これは、末尾のものも含めて、空の要素を除外しません。

31
ppeterka

String.split()APIドキュメント から:

与えられた正規表現のマッチの周りでこの文字列を分割します。このメソッドは、与えられた式とlimit引数にゼロを指定して2引数のsplitメソッドを呼び出すのと同じように機能します。したがって、末尾の空の文字列は結果の配列に含まれません。

オーバーロードされた String.split(regex、int) があなたの場合にはより適切です。

4
PermGenError

もう1つの選択肢は、Guavaのスプリッタを使用することです。正規表現によるオーバーヘッドはありません(この場合は必要ありません)。デフォルトでは、空の末尾の文字列は破棄されません。

例えば:

 String data = "5|6|7||8|9||";
 Iterable<String> results = Splitter.on('|').split(data);
 // convert to array
 String[] asArray = Iterables.toArray(results, String.class);

詳細についてはwikiを参照してください。 https://github.com/google/guava/wiki/StringsExplained

3
nickool

String[] split = data.split("\\|",-1);

これは常に実際の要件ではありません。上記の欠点は以下のとおりです。

Scenerio 1:
When all data are present:
    String data = "5|6|7||8|9|10|";
    String[] split = data.split("\\|");
    String[] splt = data.split("\\|",-1);
    System.out.println(split.length); //output: 7
    System.out.println(splt.length); //output: 8

データが欠落している場合

Scenerio 2: Data Missing
    String data = "5|6|7||8|||";
    String[] split = data.split("\\|");
    String[] splt = data.split("\\|",-1);
    System.out.println(split.length); //output: 5
    System.out.println(splt.length); //output: 8

欠けているデータがありますが、実際の要件は長さが7であるべきです。データベースなどに挿入する必要がある場合などがあるからです。以下のアプローチを使用してこれを達成できます。

    String data = "5|6|7||8|||";
    String[] split = data.split("\\|");
    String[] splt = data.replaceAll("\\|$","").split("\\|",-1);
    System.out.println(split.length); //output: 5
    System.out.println(splt.length); //output:7

ここでやったことは、 "|"を削除していることです。最後にパイプを挿入してからStringを分割します。 "、"が区切り文字としてある場合は、replaceAllの中に "、$"を追加する必要があります。

2

空白文字、カンマ、セミコロンなどを含む複数の区切り文字がある場合があります。

 String[] tokens = "a , b,  ,c; ;d,      ".split( "[,; \t\n\r]+" );

4つのトークンがあります - a、b、c、d

この分割を適用する前に、ソース文字列の先頭の区切り文字を削除する必要があります。

質問への答えとして

String data = "5|6|7||8|9||";
String[] split = data.split("[\\| \t\n\r]+");

念のために空白文字を追加してください。

1