如何初始化静态映射?

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

答案 1

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

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

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);
    }
}

答案 2

我喜欢 Guava 初始化静态、不可变映射的方式:

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

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

如果希望地图具有 5 个以上的条目,则无法再使用 。相反,请按照以下思路尝试ImmutableMap.builder():ImmutableMap.of()

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

要了解有关番石榴不可变采集实用程序的优势的更多信息,请参阅番石榴用户指南中的不可变采集说明

(子集)番石榴曾经被称为Google Collections。如果您还没有在Java项目中使用此库,我强烈建议您尝试一下!Guava已迅速成为Java最受欢迎和最有用的免费第三方库之一,正如SO用户所同意的那样。(如果你是新手,那么这个链接背后有一些很好的学习资源。


更新(2015):至于Java 8,好吧,我仍然会使用Guava方法,因为它比其他任何东西都干净。如果你不想要番石榴依赖,考虑一个普通的旧初始化方法。如果你问我,使用二维数组和Stream API的黑客是非常丑陋的,如果你需要创建一个键和值不是相同类型的Map(就像在问题中一样),它会变得更加丑陋。Map<Integer, String>

至于Guava的未来,关于Java 8,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"
);