如何在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");
        }
    };
}

当前回答

现在Java 8已经发布了,这个问题值得重新审视。我尝试了一下——看起来也许你可以利用lambda表达式语法来获得一个非常漂亮和简洁(但类型安全)的映射文字语法,看起来像这样:

Map<String,Object> myMap = hashMap(
    bob -> 5,
    TheGimp -> 8,
    incredibleKoolAid -> "James Taylor",
    heyArnold -> new Date()
);

Map<String,Integer> typesafeMap = treeMap(
    a -> 5,
    bee -> 8,
    sea -> 13
    deep -> 21
);

未经测试的示例代码在https://gist.github.com/galdosd/10823529 会对其他人对此的看法感到好奇(这有点邪恶…)

其他回答

你可以使用Cactoos中的StickyMap和MapEntry:

private static final Map<String, String> MAP = new StickyMap<>(
  new MapEntry<>("name", "Jeffrey"),
  new MapEntry<>("age", "35")
);

我不喜欢静态初始化语法,我不相信匿名子类。一般来说,我同意前面的回答中提到的使用静态初始化器的所有缺点和使用匿名子类的所有缺点。另一方面,这些文章中的优点对我来说是不够的。我更喜欢使用静态初始化方法:

public class MyClass {
    private static final Map<Integer, String> myMap = prepareMap();

    private static Map<Integer, String> prepareMap() {
        Map<Integer, String> hashMap = new HashMap<>();
        hashMap.put(1, "one");
        hashMap.put(2, "two");

        return hashMap;
    }
}

实例初始化器在这里只是语法糖,对吧?我不明白为什么需要一个额外的匿名类来初始化。如果创建的类是final类,那么它将不起作用。

你也可以使用静态初始化器创建一个不可变映射:

public class Test {
    private static final Map<Integer, String> myMap;
    static {
        Map<Integer, String> aMap = ....;
        aMap.put(1, "one");
        aMap.put(2, "two");
        myMap = Collections.unmodifiableMap(aMap);
    }
}

这一个使用Apache common -lang,它很可能已经在你的类路径上了:

Map<String, String> collect = Stream.of(
        Pair.of("hello", "world"),
        Pair.of("abc", "123"),
        Pair.of("java", "eight")
).collect(Collectors.toMap(Pair::getKey, Pair::getValue));

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来尝试这些特性。