如何在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中,过程方法也可以包装在Supplier中:

Map<String,String> m = ((Supplier<Map<String,String>>)(() -> {
    Map<String,String> result = new HashMap<>();
    result.put("foo","hoo");
    ...
    return result;
)).get();

这只是一种假设的方法,但如果您确实需要一行代码,则可以派上用场。

其他回答

第二个方法的一个优点是,你可以用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!

地图。Java 9+中的

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

详见JEP 269。JDK 9在2017年9月全面上市。

您正在创建的匿名类工作得很好。但是,您应该知道这是一个内部类,因此,它将包含对周围类实例的引用。所以你会发现你不能用它做某些事情(使用XStream为一个)。你会得到一些非常奇怪的错误。

话虽如此,但只要你意识到这种方法是可行的。我大部分时间都使用它以简洁的方式初始化各种类型的集合。

编辑:在评论中正确指出这是一个静态类。显然我没有仔细阅读。然而,我的评论仍然适用于匿名内部类。

第二种方法(双括号初始化)被认为是一种反模式,因此我将采用第一种方法。

另一个初始化静态Map的简单方法是使用这个实用函数:

public static <K, V> Map<K, V> mapOf(Object... keyValues) {
    Map<K, V> map = new HashMap<>(keyValues.length / 2);

    for (int index = 0; index < keyValues.length / 2; index++) {
        map.put((K)keyValues[index * 2], (V)keyValues[index * 2 + 1]);
    }

    return map;
}

Map<Integer, String> map1 = mapOf(1, "value1", 2, "value2");
Map<String, String> map2 = mapOf("key1", "value1", "key2", "value2");

注意:在Java 9中你可以使用Map.of

我强烈建议使用“双大括号初始化”风格而不是静态块风格。

有人可能会说他们不喜欢匿名类、开销、性能等。

但我更多考虑的是代码的可读性和可维护性。从这个角度来看,我认为双大括号是一种比静态方法更好的代码风格。

元素是嵌套的和内联的。 它更偏向于面向对象,而不是程序性的。 性能影响非常小,可以忽略不计。 更好的IDE大纲支持(而不是许多匿名的静态{}块) 你节省了几行评论来给他们带来关系。 从异常和字节码优化器防止未初始化对象的可能的元素泄漏/实例导致。 不用担心静态块的执行顺序。

此外,如果你知道匿名类的GC,你总是可以通过使用新的HashMap(Map Map)将其转换为普通的HashMap。

你可以这样做,直到你遇到另一个问题。如果你这样做,你应该使用完全另一种编码风格(例如,没有静态的,工厂类)。