如何在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");
}
};
}
我强烈建议使用“双大括号初始化”风格而不是静态块风格。
有人可能会说他们不喜欢匿名类、开销、性能等。
但我更多考虑的是代码的可读性和可维护性。从这个角度来看,我认为双大括号是一种比静态方法更好的代码风格。
元素是嵌套的和内联的。
它更偏向于面向对象,而不是程序性的。
性能影响非常小,可以忽略不计。
更好的IDE大纲支持(而不是许多匿名的静态{}块)
你节省了几行评论来给他们带来关系。
从异常和字节码优化器防止未初始化对象的可能的元素泄漏/实例导致。
不用担心静态块的执行顺序。
此外,如果你知道匿名类的GC,你总是可以通过使用新的HashMap(Map Map)将其转换为普通的HashMap。
你可以这样做,直到你遇到另一个问题。如果你这样做,你应该使用完全另一种编码风格(例如,没有静态的,工厂类)。
我会用:
public class Test {
private static final Map<Integer, String> MY_MAP = createMap();
private static Map<Integer, String> createMap() {
Map<Integer, String> result = new HashMap<>();
result.put(1, "one");
result.put(2, "two");
return Collections.unmodifiableMap(result);
}
}
它避免了匿名类,我个人认为这是一种糟糕的风格,并避免
它使地图的创建更加明确
它使地图不可修改
因为MY_MAP是常量,所以我把它命名为常量
在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之外的任何东西
它是类型安全的,很容易容纳不同类型的键和值。
这里有一些很好的答案,但我想再提供一个。
创建自己的静态方法来创建和初始化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);