はじめに
文字列を一文字ずつ解析して何か処理する時に、for文を使わずに処理できないのかなぁと調べていたらsplitに行きつきました。サンプルコードも交えて記事にしています。
実行環境
開発環境
Visual Studio Code + Java + Windows環境で実行しています。
開発環境の構築は、以下の記事を基に作成しています。
バージョンについて
以降で記載しているサンプルコードは、Java 11を使って確認しています。
実行方法
文字列を1文字ずつバラバラにするには、splitメソッドの引数に空文字を指定すればよいです。
サンプルコード
public class SplitSample {
public static void main(String[] args) {
final String SPLIT_STRING = "HELLO";
String[] array = SPLIT_STRING.split("");
for (String s : array) {
System.out.println(s);
}
}
}
ポイント
5行目:splitメソッドの引数に空文字を指定しています。これで、変数arrayには”HELLO”が1文字ずつに分割された配列が設定されます。
出力結果
手元の実行環境で動かした結果です。
ターミナル内容
PS C:\JavaWorkspace> javac -encoding UTF-8 SplitSample.java
PS C:\JavaWorkspace> java "-Dfile.encoding=UTF-8" SplitSample
H
E
L
L
O
一文字ずつ出力されていることがわかりますね。
目的のコードに近づける
さて、上のサンプルコードだと結局拡張for文を使っているので、目的のコードに近づけます。サンプルコードでは結果を分かりやすくするためにprintln()を使用しましたが、実際の結果に欲しかったのは
“HHEELLLLOO”
という文字列だったので、この文字列を作ります。
注意
この項のコードはStreamを利用してプログラムコードを作成しています。
サンプルコード
import java.util.*;
import java.util.stream.*;
public class SplitSample {
public static void main(String[] args) {
final String SPLIT_STRING = "HELLO";
String str = Arrays.stream(SPLIT_STRING.split(""))
.map(s -> s.repeat(2))
.collect(Collectors.joining()));
System.out.println(str);
}
}
ポイント
7行目:Arraysクラスを使ってsplitの結果をstreamに変換する。
8行目:それぞれの文字を2文字ずつにする。(stream.map()を使用)
9行目:collectでstreamの要素を連結する。(Collectors.joining()を使用し、区切り文字無しで連結)
10行目:連結した文字列を表示しておしまい。
出力結果
PS C:\JavaWorkspace> javac -encoding UTF-8 SplitSample.java
PS C:\JavaWorkspace> java "-Dfile.encoding=UTF-8" SplitSample
HHEELLLLOO
for文を使わずに、意図した結果の文字列が表示されました。
おまけ
splitを使わずにfor文を使って書いたコードが、以下のサンプルコードです。
サンプルコード(for文)
public class SplitSample {
public static void main(String[] args) {
final String SPLIT_STRING = "HELLO";
String[] forArray = new String[SPLIT_STRING.length()];
for (int i = 0; i < SPLIT_STRING.length(); i++) {
forArray[i] = String.valueOf(SPLIT_STRING.charAt(i)).repeat(2);
}
for (String s : forArray) {
System.out.print(s);
}
System.out.println(s);
}
}
5行目:配列用の変数を用意します。1文字ずつ分割するので、配列長 = 文字列長となります。
8行目:要素位置にあたる文字をStringに変換して、repeatメソッドで文字を2つにします。
10行目~:配列要素を順次出力し、13行目で改行のみ出力しています。
おまけを書いた感想
StreamなどがないJava7以前の環境だと、こういう風に書くのかなぁと思いながら書いてました。
最後に
この挙動、特にJavadocとかに書かれてるわけでもないですが、知っている人も結構見かける割と知られていそうな小ネタでした。
ただ、正規表現を調べてみても、空文字指定したときの挙動がどうにも見つからないので、実際のところはどういう仕様で動くものなのだろうか。
ちなみにPatternクラスや、Matcherクラスのfindメソッドとかも眺めてみたのですが、途中で追うのがしんどくなったのでやめました。。。Patternクラスの生成時、空文字がpatternに指定された場合の分岐もあるから、その辺の考慮も含めて実装されているんだなぁと思いました。
コメント