Map型のインスタンス変数やクラス変数に”格好良く”初期値を与える方法(2)

Pocket

前回の続きです。

ネットで色々と探していると、次の二つの方法が見つかりました。

import static util.Literals.map;
import java.util.Map;
import util.MapBuilder;

public class User {
	Map<String,Integer> map1 = map("hello",1).map("world",2).map("!",3);

	Map<String, Integer> map2 =
		    new MapBuilder<String, Integer>(new Object[] {
		        "hoge", 10,
		        "fuga", 20,
		        "hahe", 30
		    }).build();
}

上は[JAVA MAP LITERALS, CONTINUED]、下は[Java の Map の初期化がダサいのでどうにかしたい]で紹介されているやり方です。この記事には呼び出し元のソースコードしか載せませんので、呼び出し先の実装に興味のある方はリンク先の記事を読んでみてください。

上の書き方はjQuery界隈で人気爆発中のメソッドチェーンによる記述になっています。個人的に、これ嫌いなんです。JavaのStringBuilderのsb.append(“hoge”).append(“huga”).append(“foo”)・・・と繋ぐ様な場合は直感的なので嫌いじゃないのですが、例えば今回のmap().map().map()・・・は記述が簡単にはなりますが、直感的とは言えないです。
下はどうでしょう。これが私の好みに近いです。

私ならこうする

これらを参考に、私好みに変えさせていただきます。
呼び出し方は、こうです。

import java.util.HashMap;
import java.util.Map;

import net.risaiku.util.MapUtil;

public class User {
	Map<String, Integer> map1 = MapUtil.apply(new HashMap(),
			"foo", 1,
			"bar", 2
			);
	static Map<String, Integer> map2 = MapUtil.apply(new HashMap(),
			"foo", 1,
			"bar", 2
			);
	public static void main(String[] args) {
		Map<String, Integer> map = MapUtil.apply(new HashMap(),
				"foo", 1,
				"bar", 2
				);
	}
	public void method() {
		Map<String, Integer> map = MapUtil.apply(new HashMap(),
				"foo", 1,
				"bar", 2
				);
	}
}

当然ですが、インスタンス変数やクラス変数だけじゃなくローカル変数でも使えます。

MapUtilの方の実装は、こうです。

package net.risaiku.util;

import java.util.Map;

public class MapUtil {
	public static Map apply(Map map, Object... keyValue) {
		if(keyValue.length % 2 != 0) throw new IllegalArgumentException();
		for(int i=0; i<keyValue.length; i+=2) {
			map.put(keyValue[i], keyValue[i+1]);
		}
		return map;
	}
}

まず、引数にMapのインスタンスを受け取るようにします。
HashMapじゃなくて、WeakHashMapやConcurrentHashMapを使いたい場合もあるので。
Class型で受け取って、applyメソッド内で生成してもいいのですが、そこまでしなくも良いかと。
引数はObject型の可変長引数にしています。

・・・ごめんなさい。やっぱ格好良くならないです。
言語としてのサポートがないと限界があるのではないでしょうか。
もっと格好良い方法があれば、ぜひ教えてください。

Pocket

コメントを残す

メールアドレスが公開されることはありません。