如何在Java中初始化一个静态Map ?
方法一:静态初始化器
方法二:实例初始化器(匿名子类)
或
还有别的方法吗?
它们各自的优点和缺点是什么?
下面是一个例子来说明这两种方法:
import java.util.HashMap;
import java.util.Map;
public class Test {
private static final Map<Integer, String> myMap = new HashMap<>();
static {
myMap.put(1, "one");
myMap.put(2, "two");
}
private static final Map<Integer, String> myMap2 = new HashMap<>(){
{
put(1, "one");
put(2, "two");
}
};
}
我已经读了答案,我决定写我自己的地图生成器。请随意复制粘贴并欣赏。
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* A tool for easy creation of a map. Code example:<br/>
* {@code MapBuilder.of("name", "Forrest").and("surname", "Gump").build()}
* @param <K> key type (inferred by constructor)
* @param <V> value type (inferred by constructor)
* @author Vlasec (for http://stackoverflow.com/a/30345279/1977151)
*/
public class MapBuilder <K, V> {
private Map<K, V> map = new HashMap<>();
/** Constructor that also enters the first entry. */
private MapBuilder(K key, V value) {
and(key, value);
}
/** Factory method that creates the builder and enters the first entry. */
public static <A, B> MapBuilder<A, B> mapOf(A key, B value) {
return new MapBuilder<>(key, value);
}
/** Puts the key-value pair to the map and returns itself for method chaining */
public MapBuilder<K, V> and(K key, V value) {
map.put(key, value);
return this;
}
/**
* If no reference to builder is kept and both the key and value types are immutable,
* the resulting map is immutable.
* @return contents of MapBuilder as an unmodifiable map.
*/
public Map<K, V> build() {
return Collections.unmodifiableMap(map);
}
}
编辑:最近,我经常发现公共静态方法,我有点喜欢它。我将它添加到代码中,并使构造函数私有,从而切换到静态工厂方法模式。
EDIT2:甚至最近,我不再喜欢被称为of的静态方法,因为它在使用静态导入时看起来非常糟糕。我将其重命名为mapOf,使其更适合静态导入。
在Java 8中,过程方法也可以包装在Supplier中:
Map<String,String> m = ((Supplier<Map<String,String>>)(() -> {
Map<String,String> result = new HashMap<>();
result.put("foo","hoo");
...
return result;
)).get();
这只是一种假设的方法,但如果您确实需要一行代码,则可以派上用场。
因为Java不支持地图文字,所以必须始终显式地实例化和填充地图实例。
幸运的是,在Java中可以使用工厂方法来近似映射字面量的行为。
例如:
public class LiteralMapFactory {
// Creates a map from a list of entries
@SafeVarargs
public static <K, V> Map<K, V> mapOf(Map.Entry<K, V>... entries) {
LinkedHashMap<K, V> map = new LinkedHashMap<>();
for (Map.Entry<K, V> entry : entries) {
map.put(entry.getKey(), entry.getValue());
}
return map;
}
// Creates a map entry
public static <K, V> Map.Entry<K, V> entry(K key, V value) {
return new AbstractMap.SimpleEntry<>(key, value);
}
public static void main(String[] args) {
System.out.println(mapOf(entry("a", 1), entry("b", 2), entry("c", 3)));
}
}
输出:
{a=1, b=2, c=3}
这比一次创建和填充一个元素要方便得多。
我做了一些不同的事情。不是最好的,但对我有用。也许它可以被“泛化”。
private static final Object[][] ENTRIES =
{
{new Integer(1), "one"},
{new Integer(2), "two"},
};
private static final Map myMap = newMap(ENTRIES);
private static Map newMap(Object[][] entries)
{
Map map = new HashMap();
for (int x = 0; x < entries.length; x++)
{
Object[] entry = entries[x];
map.put(entry[0], entry[1]);
}
return map;
}
Java 8与流:
private static final Map<String, TemplateOpts> templates = new HashMap<>();
static {
Arrays.stream(new String[][]{
{CUSTOMER_CSV, "Plantilla cliente", "csv"}
}).forEach(f -> templates.put(f[0], new TemplateOpts(f[1], f[2])));
}
它也可以是Object[][],用于在forEach循环中放入任何东西并将其映射
在这种情况下,我绝不会创建匿名子类。静态初始化器同样有效,如果你想让映射不可修改,例如:
private static final Map<Integer, String> MY_MAP;
static
{
Map<Integer, String>tempMap = new HashMap<Integer, String>();
tempMap.put(1, "one");
tempMap.put(2, "two");
MY_MAP = Collections.unmodifiableMap(tempMap);
}