JavaでもRubyみたいなMap(Hash)のリテラルが欲しい!
と思って考えてみました。
Javaで適当なMap作るときって、
Map<String, String> map = new HashMap<String, String>(); map.put("tako", "octopus"); map.put("ika", "squid"); map.put("namako", "sea cucumber");
ってな感じじゃないですか?
RubyとかだとMap(RubyだとHash)のリテラルがあるんで、
hash = {"tako" => "octopus", "ika" => "squid", "namako" => "sea cucumber"}
と書けて楽です。
ScalaにもOGNLにもこんな感じの記法があるので是非Javaにもって思うんですが、ないんですよね…。
で、この前もうちょっと楽に書けないかと思って、こんなクラスを作ってみました。
public final class ColUtil { public static class FluentMap<K, V> extends LinkedHashMap<K, V> { public FluentMap<K, V> p(K key, V value) { this.put(key, value); return this; } } public static FluentMap<Object, Object> $m(Object key, Object value) { return new FluentMap<Object, Object>().p(key, value); } public static FluentMap<String, Object> $m_so(String key, Object value) { return new FluentMap<String, Object>().p(key, value); } public static FluentMap<String, String> $m_ss(String key, String value) { return new FluentMap<String, String>().p(key, value); } }
使い方はこんな感じ。
import static com.tetz42.util.ColUtil.*; : // ↑と同じ例 Map<String, String> map = $m_ss("tako", "octopus").p("ika", "squid") .p("namako", "sea cucumber"); // その他のメソッドの使用例 Map<Object, Object> map1 = $m("key1", "value1").p(0, 99); Map<String, Object> map2 = $m_so("One", 1).p("Two", 2) .p("Threee", new RuntimeException()); :
リテラルっぽさを出したかったので、各staticメソッドの先頭に「$」つけてます。
なお、FluentMapをLinkedHashMapから継承させてるのは、書いた順番を保持したいケースもありそうに思ったからです。
OGNLもデフォルトでLinkedHashMapらしいですし。
Map版のほかにList版とSet版も作ったんですが、予想つくと思うんでソースは省略します。
Listの要素がMapになっている例
Rubyだと、
list = [ {"name" => "John", "sex" => "male"}, {"name" => "Linda", "sex" => "female"}, {"name" => "Taro", "sex" => "2 times per week"} ]
と書けます。
で、今回のColUtilを使うとこんな感じです。
import static com.tetz42.util.ColUtil.*; import com.tetz42.util.ColUtil.FluentList; : // このメソッドを作成する必要あり! public static FluentList<Map<String, String>> $lm(Map<String, String> map) { return new FluentList<Map<String, String>>().a(map); } : List<Map<String, String>> list = $lm($m_ss("name", "John" ).p("sex", "male")) .a($m_ss("name", "Linda").p("sex", "female")) .a($m_ss("name", "Taro" ).p("sex", "2 times per week")); :