質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

5225閲覧

java7におけるString#split()で区切り文字を含め分割するとき空要素をできないようにしたい

sakata_inu

総合スコア25

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2018/09/04 16:28

編集2018/09/06 00:12

##文字列を区切り文字を含む形でスマートに分割したい

java7ではString#split()で文字列を分割したとき、1番目の要素に空文字ができてしまうことがあります。
そこで以下のコードを実行したとき、str2とstr3の先頭要素に空要素ができないような分割を行いたいです。

正規表現に関しては知識がないので自力で考えられる解決策としては、分割した配列の1番目の要素が空文字なら横に詰める方法です。
しかし、正規表現だけで解決できるのであればご教授いただければと思います。

java8ではString#split()のその点が改善されているようですがjava7でお願いします。

java7

1import java.util.Arrays; 2 3public class Test1 { 4 5 public static void main(String[] args) { 6 7 String regex = "(?=◆)"; 8 9 String str1 = "◆ABCD123"; 10 String str2 = "◆ABCD123◆ABCD123"; 11 String str3 = "◆ABCD123◆ABCD123◆"; 12 String str4 = "ABCD123"; 13 String str5 = ""; 14 String str6 = "ABCD123◆ABCD123"; 15 16 String[] ary1 = str1.split(regex); 17 String[] ary2 = str2.split(regex); 18 String[] ary3 = str3.split(regex); 19 String[] ary4 = str4.split(regex); 20 String[] ary5 = str5.split(regex); 21 String[] ary6 = str6.split(regex); 22 23 System.out.println(Arrays.toString(ary1)); 24 System.out.println(Arrays.toString(ary2)); 25 System.out.println(Arrays.toString(ary3)); 26 System.out.println(Arrays.toString(ary4)); 27 System.out.println(Arrays.toString(ary5)); 28 System.out.println(Arrays.toString(ary6)); 29 } 30} 31

実行結果

【実際の結果】

[◆ABCD123] [, ◆ABCD123, ◆ABCD123] [, ◆ABCD123, ◆ABCD123, ◆] [ABCD123] [] [ABCD123, ◆ABCD123]

【理想とする結果】

[◆ABCD123] [◆ABCD123, ◆ABCD123] [◆ABCD123, ◆ABCD123, ◆] [ABCD123] [] [ABCD123, ◆ABCD123]

上記で書いた横に詰める解決案

java

1import java.util.ArrayList; 2import java.util.Arrays; 3import java.util.List; 4 5public class Test2 { 6 7 public static void main(String[] args) { 8 9 String regex = "(?=◆)"; 10 11 String str1 = "◆ABCD123"; 12 String str2 = "◆ABCD123◆ABCD123"; 13 String str3 = "◆ABCD123◆ABCD123◆"; 14 String str4 = "ABCD123"; 15 String str5 = ""; 16 String str6 = "ABCD123◆ABCD123"; 17 18 String[] ary1 = split(str1, regex); 19 String[] ary2 = split(str2, regex); 20 String[] ary3 = split(str3, regex); 21 String[] ary4 = split(str4, regex); 22 String[] ary5 = split(str5, regex); 23 String[] ary6 = split(str6, regex); 24 25 System.out.println(Arrays.toString(ary1)); 26 System.out.println(Arrays.toString(ary2)); 27 System.out.println(Arrays.toString(ary3)); 28 System.out.println(Arrays.toString(ary4)); 29 System.out.println(Arrays.toString(ary5)); 30 System.out.println(Arrays.toString(ary6)); 31 } 32 33 private static String[] split(String str, String regex) { 34 String[] ary = str.split(regex); 35 36 if (ary.length >= 2 && ary[0].equals("")) { 37 List<String> tmp = new ArrayList<>(Arrays.asList(ary)); 38 tmp.remove(0); 39 ary = tmp.toArray(new String[0]); 40 } 41 42 return ary; 43 } 44}

追記

java8ではString#split()のその点が改善されているようですがjava7でお願いします。

この点に関して実際に試してみました。

【実行コード】

java

1import java.util.Arrays; 2 3public class Test { 4 5 public static void main(String[] args) { 6 7 String regex = "(?=◆)"; 8 9 String str1 = "◆ABCD123"; 10 String str2 = "◆ABCD123◆ABCD123"; 11 String str3 = "◆ABCD123◆ABCD123◆"; 12 String str4 = "ABCD123"; 13 String str5 = ""; 14 String str6 = "ABCD123◆ABCD123"; 15 16 String[] ary1 = str1.split(regex); 17 String[] ary2 = str2.split(regex); 18 String[] ary3 = str3.split(regex); 19 String[] ary4 = str4.split(regex); 20 String[] ary5 = str5.split(regex); 21 String[] ary6 = str6.split(regex); 22 23 // Javaのバージョンを出力 24 System.out.println("java.version : " + System.getProperty("java.version")); 25 System.out.println("java.vm.version : " + System.getProperty("java.vm.version")); 26 System.out.println(); 27 28 System.out.println(Arrays.toString(ary1)); 29 System.out.println(Arrays.toString(ary2)); 30 System.out.println(Arrays.toString(ary3)); 31 System.out.println(Arrays.toString(ary4)); 32 System.out.println(Arrays.toString(ary5)); 33 System.out.println(Arrays.toString(ary6)); 34 } 35}

実行結果

【Java7】

java.version : 1.7.0_80 java.vm.version : 24.80-b11 [◆ABCD123] [, ◆ABCD123, ◆ABCD123] [, ◆ABCD123, ◆ABCD123, ◆] [ABCD123] [] [ABCD123, ◆ABCD123]

【Java8】

java.version : 1.8.0_71 java.vm.version : 25.71-b15 [◆ABCD123] [◆ABCD123, ◆ABCD123] [◆ABCD123, ◆ABCD123, ◆] [ABCD123] [] [ABCD123, ◆ABCD123]

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

spookybird

2018/09/04 23:47

素朴な疑問です。Java7のサポートはすでに終了していますが、今あえてJava7で書くのはなぜですか。商用なら最低でもJava8にすべきですし、今から勉強するならJava10以降が良いと思うんですが...
swordone

2018/09/05 00:03

Java8でsplitが改善されたというのはどこの情報ですか?
spookybird

2018/09/05 00:15

業務上の縛りって...商用でJava7使ってるなら速やかにJava8にバージョンアップすべきだと思いますよ。で、Java8でsplitの挙動が変わってるなら実装も変わってるんだと思いますので、Java8のsplitの実装見て同じように実装したらいいんじゃないですか。
sakata_inu

2018/09/05 00:49

そうですね・・・。上司に打診してみます。
swordone

2018/09/05 01:41

splitの挙動の違いは、空文字で切った場合の話であって、そうでない場合は多分7でも8でも変わらないと思います。
spookybird

2018/09/05 13:34 編集

Oracle Java SE 7 と 8 のソースでsplitの差分取ってみたんですが、処理に変更はないですね。ブラケットの省略をやめたってこと以外の差分がありませんでした。 http://mergely.com/3r8z5gsV/
sakata_inu

2018/09/06 00:20 編集

まず、質問にあった件ですがJava8に移行するよう検討するみたいなのでJava7での挙動は考えなくても良くなりました。なので本件をクローズしたいのですがこの場合、削除でよいのでしょうか。 それと、Java7とJava8で実際に試したところやはり挙動は変わるようです。差分を見る限り違いはなさそうですがなぜでしょうか・・・。
spookybird

2018/09/06 01:25

それPatternクラスのsplitなので違うのでは…?質問のコードだとStringのsplitメソッド呼ばれてると思うんですが
sakata_inu

2018/09/06 01:52

たぶん asahina1979さんがおっしゃっているのは、String#split()内部でPattern#split()が呼ばれているので、挙動の差異はそこで出ているということだと思います。ご提示いただいたサイトを使わせて頂くと http://mergely.com/3r8z5gsV/ の52行目あるいは54行目。違っていたらすみません。
退会済みユーザー

退会済みユーザー

2018/09/06 02:01

質問者さん、そこの認識で間違いないですよ
guest

回答1

0

ベストアンサー

正規表現による split のため

// java 7 // Add segments before each match found while(m.find()) { if (!matchLimited || matchList.size() < limit - 1) { String match = input.subSequence(index, m.start()).toString(); matchList.add(match); index = m.end(); } else if (matchList.size() == limit - 1) { // last one String match = input.subSequence(index, input.length()).toString(); matchList.add(match); index = m.end(); } }
// java 8 // Add segments before each match found while(m.find()) { if (!matchLimited || matchList.size() < limit - 1) { if (index == 0 && index == m.start() && m.start() == m.end()) { // no empty leading substring included for zero-width match // at the beginning of the input char sequence. continue; } String match = input.subSequence(index, m.start()).toString(); matchList.add(match); index = m.end(); } else if (matchList.size() == limit - 1) { // last one String match = input.subSequence(index, input.length()).toString(); matchList.add(match); index = m.end(); } }

投稿2018/09/06 00:53

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sakata_inu

2018/09/07 01:04

回答ありがとうございます。やはり仕様上正規表現だけでは難しいので、判定処理を挟むのがベストなのでしょうか。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問