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

当前回答

使用Eclipse Collections,以下所有功能都可以工作:

import java.util.Map;

import org.eclipse.collections.api.map.ImmutableMap;
import org.eclipse.collections.api.map.MutableMap;
import org.eclipse.collections.impl.factory.Maps;

public class StaticMapsTest
{
    private static final Map<Integer, String> MAP =
        Maps.mutable.with(1, "one", 2, "two");

    private static final MutableMap<Integer, String> MUTABLE_MAP =
       Maps.mutable.with(1, "one", 2, "two");


    private static final MutableMap<Integer, String> UNMODIFIABLE_MAP =
        Maps.mutable.with(1, "one", 2, "two").asUnmodifiable();


    private static final MutableMap<Integer, String> SYNCHRONIZED_MAP =
        Maps.mutable.with(1, "one", 2, "two").asSynchronized();


    private static final ImmutableMap<Integer, String> IMMUTABLE_MAP =
        Maps.mutable.with(1, "one", 2, "two").toImmutable();


    private static final ImmutableMap<Integer, String> IMMUTABLE_MAP2 =
        Maps.immutable.with(1, "one", 2, "two");
}

您还可以使用Eclipse Collections静态地初始化原始映射。

import org.eclipse.collections.api.map.primitive.ImmutableIntObjectMap;
import org.eclipse.collections.api.map.primitive.MutableIntObjectMap;
import org.eclipse.collections.impl.factory.primitive.IntObjectMaps;

public class StaticPrimitiveMapsTest
{
    private static final MutableIntObjectMap<String> MUTABLE_INT_OBJ_MAP =
            IntObjectMaps.mutable.<String>empty()
                    .withKeyValue(1, "one")
                    .withKeyValue(2, "two");

    private static final MutableIntObjectMap<String> UNMODIFIABLE_INT_OBJ_MAP =
            IntObjectMaps.mutable.<String>empty()
                    .withKeyValue(1, "one")
                    .withKeyValue(2, "two")
                    .asUnmodifiable();

    private static final MutableIntObjectMap<String> SYNCHRONIZED_INT_OBJ_MAP =
            IntObjectMaps.mutable.<String>empty()
                    .withKeyValue(1, "one")
                    .withKeyValue(2, "two")
                    .asSynchronized();

    private static final ImmutableIntObjectMap<String> IMMUTABLE_INT_OBJ_MAP =
            IntObjectMaps.mutable.<String>empty()
                    .withKeyValue(1, "one")
                    .withKeyValue(2, "two")
                    .toImmutable();

    private static final ImmutableIntObjectMap<String> IMMUTABLE_INT_OBJ_MAP2 =
            IntObjectMaps.immutable.<String>empty()
                    .newWithKeyValue(1, "one")
                    .newWithKeyValue(2, "two");
} 

注意:我是Eclipse Collections的提交者

其他回答

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

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

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

这里有一些很好的答案,但我想再提供一个。

创建自己的静态方法来创建和初始化Map。我在一个包中有自己的CollectionUtils类,我在项目中使用各种我经常使用的实用程序,这些实用程序对我来说很容易编写,并且避免了对一些大型库的依赖。

这是我的newMap方法:

public class CollectionUtils {
    public static Map newMap(Object... keyValuePairs) {
        Map map = new HashMap();
        if ( keyValuePairs.length % 2 == 1 ) throw new IllegalArgumentException("Must have even number of arguments");
        for ( int i=0; i<keyValuePairs.length; i+=2 ) {
            map.put(keyValuePairs[i], keyValuePairs[i + 1]);
        }
        return map;
    }
}

用法:

import static CollectionUtils.newMap;
// ...
Map aMap = newMap("key1", 1.23, "key2", 2.34);
Map bMap = newMap(objKey1, objVal1, objKey2, objVal2, objKey3, objVal3);
// etc...

它不使用泛型,但您可以按自己的意愿对地图进行类型转换(只是要确保您正确地进行了类型转换!)

Map<String,Double> aMap = (Map<String,Double>)newMap("key1", 1.23, "key2", 2.34);

这一个使用Apache common -lang,它很可能已经在你的类路径上了:

Map<String, String> collect = Stream.of(
        Pair.of("hello", "world"),
        Pair.of("abc", "123"),
        Pair.of("java", "eight")
).collect(Collectors.toMap(Pair::getKey, Pair::getValue));

第二个方法可以在需要时调用受保护的方法。这对于初始化构造后不可变的类很有用。