如何在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 5提供了更紧凑的语法:

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

其他回答

即使使用Guava很好的ImmutableMap类,有时我也想流畅地构建一个可变映射。发现自己想要避免静态块和匿名子类型的东西,当Java 8出现时,我写了一个小库来帮助我,叫做Fluent。

// simple usage, assuming someMap is a Map<String, String> already declared
Map<String, String> example = new Fluent.HashMap<String, String>()
    .append("key1", "val1")
    .append("key2", "val2")
    .appendAll(someMap);

与Java 8接口默认我可以实现Fluent。所有标准Java Map实现的Map方法(例如HashMap, ConcurrentSkipListMap,…)等等),没有乏味的重复。

不可修改的地图也很简单。

Map<String, Integer> immutable = new Fluent.LinkedHashMap<String, Integer>()
    .append("one", 1)
    .append("two", 2)
    .append("three", 3)
    .unmodifiable();

参见https://github.com/alexheretic/fluent获取源代码、文档和示例。

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

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

我还没有在任何答案中看到我使用的方法(并且已经逐渐喜欢上了),所以这里是:

我不喜欢使用静态初始化器,因为它们很笨拙, 我不喜欢匿名类,因为它为每个实例创建一个新类。

相反,我更喜欢这样的初始化:

map(
    entry("keyA", "val1"),
    entry("keyB", "val2"),
    entry("keyC", "val3")
);

不幸的是,这些方法不是标准Java库的一部分, 所以你需要创建(或使用)一个实用程序库,它定义了以下方法:

 public static <K,V> Map<K,V> map(Map.Entry<K, ? extends V>... entries)
 public static <K,V> Map.Entry<K,V> entry(K key, V val)

(你可以使用'import static'来避免在方法名前加上前缀)

我发现为其他集合(list、set、sortedSet、sortedMap等)提供类似的静态方法很有用。

它不像json对象初始化那样好,但就可读性而言,这是朝着那个方向迈出的一步。

我喜欢使用静态初始化“技术”,当我有一个抽象类的具体实现,它定义了一个初始化构造函数,但没有默认构造函数,但我希望我的子类有一个默认构造函数。

例如:

public abstract class Shape {

    public static final String COLOR_KEY = "color_key";
    public static final String OPAQUE_KEY = "opaque_key";

    private final String color;
    private final Boolean opaque;

    /**
     * Initializing constructor - note no default constructor.
     *
     * @param properties a collection of Shape properties
     */
    public Shape(Map<String, Object> properties) {
        color = ((String) properties.getOrDefault(COLOR_KEY, "black"));
        opaque = (Boolean) properties.getOrDefault(OPAQUE_KEY, false);
    }

    /**
     * Color property accessor method.
     *
     * @return the color of this Shape
     */
    public String getColor() {
        return color;
    }

    /**
     * Opaque property accessor method.
     *
     * @return true if this Shape is opaque, false otherwise
     */
    public Boolean isOpaque() {
        return opaque;
    }
}

以及这个类的具体实现——但它想要/需要一个默认构造函数:

public class SquareShapeImpl extends Shape {

    private static final Map<String, Object> DEFAULT_PROPS = new HashMap<>();

    static {
        DEFAULT_PROPS.put(Shape.COLOR_KEY, "yellow");
        DEFAULT_PROPS.put(Shape.OPAQUE_KEY, false);
    }

    /**
     * Default constructor -- intializes this square to be a translucent yellow
     */
    public SquareShapeImpl() {
        // the static initializer was useful here because the call to 
        // this(...) must be the first statement in this constructor
        // i.e., we can't be mucking around and creating a map here
        this(DEFAULT_PROPS);
    }

    /**
     * Initializing constructor -- create a Square with the given
     * collection of properties.
     *
     * @param props a collection of properties for this SquareShapeImpl
     */
    public SquareShapeImpl(Map<String, Object> props) {
        super(props);
    }
}

然后要使用这个默认构造函数,只需执行以下操作:

public class StaticInitDemo {

    public static void main(String[] args) {

        // create a translucent, yellow square...
        Shape defaultSquare = new SquareShapeImpl();

        // etc...
    }
}

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

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