split と join
split(".") が、なぜか空の配列を返す
外から渡ってくるデータの多くは、カンマ区切りやスラッシュ区切りといった「区切り文字でつながった 1 本の文字列」です。これをばらすのが String.split、ばらしたものを 1 本に戻すのが String.join です。
ところが、ファイル名を拡張子で分けようとした最初の 1 行でつまずきます。
Java
String path = "app.config.json";
String[] bad = path.split(".");
System.out.println(bad.length); // 0
String[] good = path.split("\\.");
System.out.println(good.length); // 3例外は出ません。長さ 0 の配列が黙って返ってきて、後ろの処理が空回りするだけです。
区切り文字は、正規表現として読まれている
split の引数は、ただの文字ではなく 正規表現 として解釈されます。正規表現の . は「任意の 1 文字」なので、split(".") は「どの文字も区切り文字」という意味になります。全部が区切りなので、残る中身が 1 つもなく、結果は空の配列です。
文字としてのドットで分けたいなら、\\. と書いて打ち消します。同じことが | ? * + ( ) [ ] { } ^ $ にも当てはまります。
Java
String[] parts = "red|green|blue".split("\\|");
System.out.println(String.join(" / ", parts)); // red / green / blue打ち消しが面倒なときは Pattern.quote("|") を通すと、中身を文字どおりに扱ってくれます。なお , や - は正規表現でも特別な意味を持たないので、そのまま渡して構いません。
String.join の方に正規表現の話はありません。第 1 引数の文字列を、要素と要素の間にそのまま挟むだけです。配列でも List でも受け取れて、末尾に余計な区切りが残らないので、自分でループを回して最後の 1 文字を削るような処理は要りません。同じ道具に見えて片方だけ正規表現、というのが混乱しやすいところです。
空の入力と、末尾の空白は数え方が違う
もう 1 つ、split の戻り値には直感に反する決まりが 2 つあります。
Java
System.out.println("".split(",").length); // 1
System.out.println("a,b,,".split(",").length); // 2空文字列を分けると、空配列ではなく空文字列 1 個が入った配列が返ります。そして末尾に続く空の要素は捨てられるので、"a,b,," は 4 要素ではなく 2 要素になります。列数を厳密に揃えたい場面では split(",", -1) と第 2 引数に負の数を渡すと、末尾の空要素も残ります。
区切り文字の周りに空白が混ざった入力はよくあります。
splitした直後に各要素をtrimしておくと、雑な入力でも安定します。
課題では、カンマで分けて中身を並べ替え、またカンマでつなぎ直します。カンマは打ち消しの要らない文字なのでそこは素直に書けますが、空文字列を渡されたときに何が返るかは、上の決まりを思い出して先に確かめておいてください。
要件
csv.split(",")を使って文字列を,で分割すること- 分割した配列を逆順に並べ替えてから
String.join(",", ...)でつなぎ直すこと csvが空文字列""のときは空文字列をそのまま返すこと
入出力例
swapJoin("a,b,c") → "c,b,a"
swapJoin("hello") → "hello"
swapJoin("") → ""
swapJoin("1,2,3,4") → "4,3,2,1"
swapJoin("foo,bar") → "bar,foo"