テンプレートのような、ある文字列の特定の文字をパラメータ文字列リストに置き換える処理は簡単だと思ってたが
以外と難しい。java.util.regex.Matcher を回した時に、置換メソッド実行していけば良いと思ってたが、
Matcher に、replaceFirst か replaceAll しかないではないか。
お題:
String str = "123456?789?01234?5"; String[] parameters = { "A", "B", "'c'" };
とあった時、'?' の文字をこの parameters の文字列に順に置換して
123456A789B01234'c'5
としたいのである。
'?' でテンプレートにあたる文字列 str を split してなんてやり方は、なんか賢くない。。
Matcher を使うことにして考えて書いたら、なんか動物的な思考のコーディングだけど以下のようなった。
Matcher m = Pattern.compile("\\?").matcher(str); List<Integer> ixlist = new ArrayList<>(); while(m.find()) ixlist.add(m.start()); Collections.reverse(ixlist); AtomicReference<String> cache = new AtomicReference<String>(str); AtomicInteger n = new AtomicInteger(parameters.length-1); ixlist.stream().forEach(i->{ cache.set(cache.get().substring(0, i) + parameters[n.get()] + cache.get().substring(i+1)); n.set(n.get()-1); }); String result = cache.get();
これで、求めてる結果を得ることができる。
Matcher の find() 後の start() の結果を逆順リストにして String#substring で文字列を作り直してる
→ なんか感情を丸出しのコードだ。
この題目を解く必要性を打ち明けると mybatis のログ、org.apache.ibatis.logging.jdbc.BaseJdbcLogger
が出力する SQL
Preparing と Parameters から、動かせるSQL文をリメイクしたかったからだ。