如何在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中,我已经开始使用以下模式:

private static final Map<String, Integer> MAP = Stream.of(
    new AbstractMap.SimpleImmutableEntry<>("key1", 1),
    new AbstractMap.SimpleImmutableEntry<>("key2", 2)
).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

这不是最简洁的,有点迂回,但是

它不需要java.util之外的任何东西 它是类型安全的,很容易容纳不同类型的键和值。

其他回答

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

实例初始化器在这里只是语法糖,对吧?我不明白为什么需要一个额外的匿名类来初始化。如果创建的类是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);
    }
}

下面是一个Java 8单行静态映射初始化器:

private static final Map<String, String> EXTENSION_TO_MIMETYPE =
    Arrays.stream(new String[][] {
        { "txt", "text/plain" }, 
        { "html", "text/html" }, 
        { "js", "application/javascript" },
        { "css", "text/css" },
        { "xml", "application/xml" },
        { "png", "image/png" }, 
        { "gif", "image/gif" }, 
        { "jpg", "image/jpeg" },
        { "jpeg", "image/jpeg" }, 
        { "svg", "image/svg+xml" },
    }).collect(Collectors.toMap(kv -> kv[0], kv -> kv[1]));

编辑:要初始化一个Map<Integer, String>,就像问题中那样,你需要这样的东西:

static final Map<Integer, String> MY_MAP = Arrays.stream(new Object[][]{
        {1, "one"},
        {2, "two"},
}).collect(Collectors.toMap(kv -> (Integer) kv[0], kv -> (String) kv[1]));

编辑(2):i_am_zero有一个更好的、支持混合类型的版本,它使用新的SimpleEntry<>(k, v)调用流。看看答案:https://stackoverflow.com/a/37384773/3950982

我做了一些不同的事情。不是最好的,但对我有用。也许它可以被“泛化”。

private static final Object[][] ENTRIES =
{
  {new Integer(1), "one"},
  {new Integer(2), "two"},
};
private static final Map myMap = newMap(ENTRIES);

private static Map newMap(Object[][] entries)
{
  Map map = new HashMap();

  for (int x = 0; x < entries.length; x++)
  {
    Object[] entry = entries[x];

    map.put(entry[0], entry[1]);
  }

  return map;
}

也许它是有趣的检查谷歌集合,例如,他们在他们的网页上的视频。它们提供了各种初始化映射和集合的方法,也提供了不可变的集合。

更新:这个库现在被命名为Guava。