Javaを書いてて、

1
2
3
4
Map<String, String> hogehogeMap = new HashMap<String,String>();
hogehogeMap .put("hoge", "fuga");
hogehogeMap .put("hoehoe", "fugafuga");

みたいなのを沢山書くのが超絶面倒だったので作っちゃいました。

Mapリテラル

package literal;
import java.util.LinkedHashMap;
import java.util.Map;
public class M {
private M(){}
public static <K, V> MapBuilder<K, V> put(K key, V value) {
MapBuilder<K, V> mapBuilder = new MapBuilder<K, V>();
return mapBuilder.put(key, value);
}
public static class MapBuilder<K, V> {
private MapBuilder(){};
private Map<K, V> map = new LinkedHashMap<K, V>();
public MapBuilder<K, V> put(K key, V value) {
map.put(key, value);
return this;
}
public Map<K, V> end() {
return map;
}
}
}
view raw literal.M.java hosted with ❤ by GitHub
お好きなパッケージ(自分は「literal」にしてみました)に突っ込んで、以下のように使います。
1
2
3
4
5
Map&lt;String,String> h = literal.M
	.put("1", "fugafuga")
	.put("2", "aaaa")
	.end();

実装について

Builderパターン(の変形)を使ってMapを生成しているだけです。ただ、可読性を高めるために以下の仕掛けを施しています

  • 「put(K key, V value)」メソッドでBuilderのオブジェクトを生成し、さらに同名の「put(K key, V value)」メソッドで値追加をすることでIDE(というより自分)を騙す。
  • Builderクラスに渡される型パラメータ(KとV)は、オブジェクト生成時(つまり、1回目のput時)に確定します。なので、代入先のMapと同じ型だけをputできます。キャスト不要で型安全。
  • 普通は「build()」とか「construct()」とかにするところを「end()」にして終わった感を出す。
ちゃんとジェネリッククラスで作成しているので、型安全です。
たとえば、
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Map&lt;String,String> h = literal.M
	.put(1, "fugafuga")
	.put("2", 2)
	.end();

Map&lt;Integer,String> h = literal.M
	.put("1", "fugafuga")
	.put("2", "2")
	.end();

みたいなコードはコンパイルエラーになります。素敵。

Listリテラル

同様にListリテラルも作ってみました。

package literal;
import java.util.ArrayList;
import java.util.List;
public class L {
private L(){}
public static <T> ListBuilder<T> add(T e) {
ListBuilder<T> listBuilder = new ListBuilder<T>();
return listBuilder.add(e);
}
public static class ListBuilder<T> {
private ListBuilder(){};
private List<T> list = new ArrayList<T>();
public ListBuilder<T> add(T e) {
list.add(e);
return this;
}
public List<T> end() {
return list;
}
}
}
view raw literal.L.java hosted with ❤ by GitHub
使い方は同じで、こんな風にします。
1
2
3
4
5
6
List&lt;String> l = literal.L
	.add("1")
	.add("fuga")
	.add("aa")
	.end();

仕組みはMapのときと同じなので説明は割愛。

まとめ

え? リテラルじゃないって?楽できて見やすいからいーのです。