Javaで文字列を分割し、区切り文字を保持する
1. 序章
プログラマーは、文字列の分割を伴うアルゴリズムに出くわすことがよくあります。 特別なシナリオでは、単一または複数の個別の区切り文字に基づいて文字列を分割する必要があり、は分割操作の一部として区切り文字も返します。
このString分割問題に対して利用可能なさまざまな解決策について詳しく説明しましょう。
2. 基礎
Javaユニバースは、単純でかなり複雑な場合に文字列の分割を容易にするために、かなりの数のライブラリ( java.lang.String 、Guava、Apache Commonsなど)を提供します。 。 さらに、機能豊富な正規表現は、特定のパターンのマッチングを中心に展開する問題を分割する際の柔軟性を高めます。
3. ルックアラウンドアサーション
正規表現では、ルックアラウンドアサーションは、ソース文字列の現在の場所で別のパターンを先読み(先読み)または後見(後読み)することで一致が可能であることを示します。 例を挙げて、これをよりよく理解しましょう。
先読みアサーションJava(?= Baeldung) は、「Baeldung」が後に続く場合にのみ「Java」と一致します。
同様に、否定的な後ろ向きの主張 (? <!#)\d+ ‘#’が前に付いていない場合にのみ数値に一致します。
このようなルックアラウンドアサーションの正規表現を使用して、問題の解決策を考案しましょう。
この記事で説明するすべての例では、2つの単純なStringを使用します。
String text = "Hello@World@This@Is@A@Java@Program";
String textMixed = "@HelloWorld@This:Is@A#Java#Program";
4. String.split()を使用する
コアJavaライブラリのStringクラスのsplit()メソッドを使用することから始めましょう。
さらに、適切な先読みアサーション、後読みアサーション、およびそれらの組み合わせを評価して、必要に応じて文字列を分割します。
4.1. ポジティブルックアヘッド
まず、先読みアサーション“((?= @))” を使用して、文字列textを一致するものに分割します。
String[] splits = text.split("((?=@))");
先読み正規表現は、“ @”記号の前方一致によって文字列を分割します。 結果の配列の内容は次のとおりです。
[Hello, @World, @This, @Is, @A, @Java, @Program]
この正規表現を使用しても、splits配列で区切り文字が個別に返されることはありません。 別のアプローチを試してみましょう。
4.2. ポジティブルックビハインド
ポジティブビハインドアサーションを使用することもできます 「((?<= @))」 文字列を分割するには文章 :
String[] splits = text.split("((?<=@))");
ただし、結果の出力には、配列の個々の要素としての区切り文字は含まれません。
[Hello@, World@, This@, Is@, A@, Java@, Program]
4.3. ポジティブルックアヘッドまたはルックビハインド
上記の2つの説明されたルックアラウンドと論理和を組み合わせて使用し、実際の動作を確認できます。
String[] splits = text.split("((?=@)|(?<=@))");
上記の正規表現は文字列を分割し、結果の配列には区切り文字が含まれます。
[Hello, @, World, @, This, @, Is, @, A, @, Java, @, Program]
必要なルックアラウンドアサーションの正規表現を理解したので、入力文字列に存在するさまざまなタイプの区切り文字に基づいて正規表現を変更できます。
適切な正規表現を使用して、前に定義したtextMixedを分割してみましょう。
String[] splitsMixed = textMixed.split("((?=:|#|@)|(?<=:|#|@))");
上記のコード行を実行した後、以下の結果が表示されるのは当然のことです。
[@, HelloWorld, @, This, :, Is, @, A, #, Java, #, Program]
5. Guava Splitterを使用する
上記のセクションで説明した正規表現のアサーションが明確になったことを考慮して、Googleが提供するJavaライブラリについて詳しく見ていきましょう。
GuavaのSplitterクラスは、正規表現パターンをセパレーターとして使用して文字列を分割するメソッド on()および onPattern()を提供します。 。
まず、単一の区切り文字“ @”を含む文字列テキストでの動作を見てみましょう。
List<String> splits = Splitter.onPattern("((?=@)|(?<=@))").splitToList(text);
List<String> splits2 = Splitter.on(Pattern.compile("((?=@)|(?<=@))")).splitToList(text);
上記のコード行を実行した結果は、配列の代わりに List があることを除けば、splitメソッドによって生成された結果と非常によく似ています。
同様に、これらのメソッドを使用して、複数の異なる区切り文字を含む文字列を分割することもできます。
List<String> splitsMixed = Splitter.onPattern("((?=:|#|@)|(?<=:|#|@))").splitToList(textMixed);
List<String> splitsMixed2 = Splitter.on(Pattern.compile("((?=:|#|@)|(?<=:|#|@))")).splitToList(textMixed);
ご覧のとおり、上記の2つの方法の違いは非常に顕著です。
on()メソッドは java.util.regex.Pattern の引数を受け入れますが、 onPattern()メソッドはセパレーター正規表現をとして受け入れるだけです。 ]文字列。
6. ApacheCommonsの使用StringUtils
Apache Commons LangプロジェクトのStringUtilsメソッドsplitByCharacterType()。を利用することもできます。
これに注意することは本当に重要です
さらに、ソース文字列の大文字と小文字が常に大文字または小文字である場合に、最良の結果が得られます。
String[] splits = StringUtils.splitByCharacterType("pg@no;10@hello;world@this;is@a#10words;Java#Program");
上記の文字列に見られるさまざまな文字タイプは、大文字と小文字、数字、および特殊文字(@;#)です。
したがって、結果の配列 splits、は、予想どおり、次のようになります。
[pg, @, no, ;, 10, @, hello, ;, world, @, this, ;, is, @, a, #, 10, words, ;, J, ava, #, P, rogram]
7. 結論
この記事では、結果の配列で区切り文字も使用できるように文字列を分割する方法を説明しました。
最初に、ルックアラウンドアサーションについて説明し、それらを使用して目的の結果を取得しました。 その後、Guavaライブラリが提供するメソッドを使用して、同様の結果を達成しました。
最後に、Apache Commons Langライブラリで締めくくりました。これは、文字列を分割し、区切り文字を返すという関連する問題を解決するための、よりユーザーフレンドリーな方法を提供します。
いつものように、この記事で使用されているコードは、GitHubのにあります。