その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

sprint という Java の string formatter を書いた

sprint という Java 向けの String formatter を書いた.

Maven Central にも置いてある.

http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22net.moznion%22%20AND%20a%3A%22sprint%22

sprint は Sprint#ff() というメソッドを提供している.使い方としては以下の様な感じ.

final Sprint sprint = new Sprint();
System.out.Println(sprint.ff("Hello: {}!", "John")); // => Hello: John!

処理としては,template を parse して placeholder とそれ以外とを検出して,その検出した placeholder に変数を埋めつつ文字列を生成している.
そしてコードを読むと分かる通り,sprint は実際には StringBuilder の wrapper のようになっていて,適宜 StringBuilder#append() を呼びながら文字列を組み立てている.

工夫などとしては以下の通り.

簡易な template

sprint では簡単な template を利用する.例えば "{}: {}" という感じ.この template 中の {} は placeholder であり,sprint はこの placeholder に対して与えられたパラメータを埋めていく.メソッドの受け取る第一引数はこの template であり,以降の引数は placeholder に埋めるためのパラメータとして扱われる.この時,このパラメータは StringBuilder#append() に渡されるので,結果的に String.valueOf() を適用した結果が文字列中に埋められる.
これは Logback の文字列 template もこんな感じだったと思う.楽で良い.

template の parse 結果を使い回す.

文字列を format する度に template を parse していては効率的ではない.template に対する parse の結果は一意のはずで,記憶しておいて以降の処理で使いまわしたとしても矛盾は起きないはず.なので sprint では template の parse 結果を template 文字列と紐付けてインスタンス内に保持し,同じ template を使った二回目以降の format の際にはその保持しておいた結果を用いる.つまり,sprint では template の parse は一度だけ実行されるということになる.
なお,sprint ではこの parse した結果の構造を走査することで文字列を生成している.

こうした処理の削減によりパフォーマンスが向上している.ベンチマークの結果としては以下の様な感じ(jdk1.8.0_92 で実行.コードはここ).

f:id:moznion:20160605223844p:plain

小さい

コードの規模は小さく,外部に対する依存がないので組み込みやすい.
あと Java 7 でも動くので Android とかでも使えそう.


という感じ.
String formatter はかねがね作りたいと思っていたのでこの土日で作ってみた次第.
どうぞご利用ください.