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

其他回答

这是我最喜欢的

不想(或不能)使用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));

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

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

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

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

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

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

我喜欢匿名类语法;只是代码更少。然而,我发现的一个主要缺点是,您将无法通过远程序列化该对象。您将得到一个关于无法在远程端找到匿名类的异常。

Java 9

我们可以用地图。ofEntries,调用Map。条目(k, v)来创建每个条目。

import static java.util.Map.entry;
private static final Map<Integer,String> map = Map.ofEntries(
        entry(1, "one"),
        entry(2, "two"),
        entry(3, "three"),
        entry(4, "four"),
        entry(5, "five"),
        entry(6, "six"),
        entry(7, "seven"),
        entry(8, "eight"),
        entry(9, "nine"),
        entry(10, "ten"));

我们也可以使用Map。如Tagir在他的回答中所建议的,但我们不能使用Map.of有超过10个条目。

Java 8

我们可以创建一个映射条目流。在java.util.AbstractMap中我们已经有两个Entry的实现,它们是SimpleEntry和SimpleImmutableEntry。在这个例子中,我们可以使用former as:

import java.util.AbstractMap.*;
private static final Map<Integer, String> myMap = Stream.of(
            new SimpleEntry<>(1, "one"),
            new SimpleEntry<>(2, "two"),
            new SimpleEntry<>(3, "three"),
            new SimpleEntry<>(4, "four"),
            new SimpleEntry<>(5, "five"),
            new SimpleEntry<>(6, "six"),
            new SimpleEntry<>(7, "seven"),
            new SimpleEntry<>(8, "eight"),
            new SimpleEntry<>(9, "nine"),
            new SimpleEntry<>(10, "ten"))
            .collect(Collectors.toMap(SimpleEntry::getKey, SimpleEntry::getValue));
            

在这种情况下,我绝不会创建匿名子类。静态初始化器同样有效,如果你想让映射不可修改,例如:

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