如何在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");
}
};
}
在这种情况下,我绝不会创建匿名子类。静态初始化器同样有效,如果你想让映射不可修改,例如:
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);
}
因为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}
这比一次创建和填充一个元素要方便得多。
JEP 269为Collections API提供了一些方便的工厂方法。该工厂方法不在当前的Java版本(即8)中,但计划在Java 9发行版中使用。
对于Map有两个工厂方法:of和ofEntries。使用of,可以交替传递键/值对。例如,为了创建一个像{age: 27, major: cs}这样的Map:
Map<String, Object> info = Map.of("age", 27, "major", "cs");
目前of有十个重载版本,因此您可以创建一个包含十个键/值对的映射。如果你不喜欢这个限制或交替键/值,你可以使用ofEntries:
Map<String, Object> info = Map.ofEntries(
Map.entry("age", 27),
Map.entry("major", "cs")
);
of和ofEntries都将返回一个不可变的Map,因此在构造之后不能更改它们的元素。您可以使用JDK 9 Early Access来尝试这些特性。
这是我最喜欢的
不想(或不能)使用Guava的ImmutableMap.of()
或者我需要一个可变Map
或者我需要从JDK9+的Map.of()中超过10个条目限制
public static <A> Map<String, A> asMap(Object... keysAndValues) {
return new LinkedHashMap<String, A>() {{
for (int i = 0; i < keysAndValues.length - 1; i++) {
put(keysAndValues[i].toString(), (A) keysAndValues[++i]);
}
}};
}
它非常紧凑,并且忽略了杂散值(即没有值的最终键)。
用法:
Map<String, String> one = asMap("1stKey", "1stVal", "2ndKey", "2ndVal");
Map<String, Object> two = asMap("1stKey", Boolean.TRUE, "2ndKey", new Integer(2));