如何在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:

static Map<Integer, String> MAP = Stream.of(
        "1=one",
        "2=two"
).collect(Collectors.toMap(k -> Integer.parseInt(k.split("=")[0]), v -> v.split("=")[1]));

其他回答

Java 5提供了更紧凑的语法:

static final Map<String , String> FLAVORS = new HashMap<String , String>() {{
    put("Up",    "Down");
    put("Charm", "Strange");
    put("Top",   "Bottom");
}};

这一个使用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));

第二个方法的一个优点是,你可以用Collections.unmodifiableMap()来包装它,以确保以后不会更新集合:

private static final Map<Integer, String> CONSTANT_MAP = 
    Collections.unmodifiableMap(new HashMap<Integer, String>() {{ 
        put(1, "one");
        put(2, "two");
    }});

 // later on...

 CONSTANT_MAP.put(3, "three"); // going to throw an exception!

我喜欢用Guava方法初始化一个静态的、不可变的映射:

static final Map<Integer, String> MY_MAP = ImmutableMap.of(
    1, "one",
    2, "two"
);

正如您所看到的,它非常简洁(因为ImmutableMap中方便的工厂方法)。

如果你想让映射有5个以上的条目,你不能再使用ImmutableMap.of()。相反,尝试ImmutableMap.builder():

static final Map<Integer, String> MY_MAP = ImmutableMap.<Integer, String>builder()
    .put(1, "one")
    .put(2, "two")
    // ... 
    .put(15, "fifteen")
    .build();

要了解更多关于Guava的不可变集合实用程序的好处,请参阅Guava用户指南中的不可变集合解释。

(一个子集)Guava过去被称为谷歌集合。如果您还没有在Java项目中使用这个库,我强烈建议您尝试一下!正如其他SO用户所认同的那样,Guava已经迅速成为Java最流行和最有用的免费第三方库之一。(如果你是新手,在这个链接后面有一些很好的学习资源。)


更新(2015):至于Java 8,嗯,我仍然会使用Guava方法,因为它比其他任何方法都要干净得多。如果不希望依赖于Guava,可以考虑使用普通的init方法。如果你问我,使用二维数组和流API的黑客是非常丑陋的,如果你需要创建一个键和值不相同类型的Map(如Map<Integer, String>在问题中),就会变得更加丑陋。

至于Guava的未来,Louis Wasserman早在2014年就说过,2016年又宣布Guava 21将需要并适当支持Java 8。


更新(2016):正如Tagir Valeev所指出的,Java 9将通过为集合添加方便的工厂方法,最终使这一工作只使用纯JDK即可完成:

static final Map<Integer, String> MY_MAP = Map.of(
    1, "one", 
    2, "two"
);

我会用:

public class Test {
    private static final Map<Integer, String> MY_MAP = createMap();

    private static Map<Integer, String> createMap() {
        Map<Integer, String> result = new HashMap<>();
        result.put(1, "one");
        result.put(2, "two");
        return Collections.unmodifiableMap(result);
    }
}

它避免了匿名类,我个人认为这是一种糟糕的风格,并避免 它使地图的创建更加明确 它使地图不可修改 因为MY_MAP是常量,所以我把它命名为常量