如何在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");
}
};
}
即使使用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获取源代码、文档和示例。
在这种情况下,我绝不会创建匿名子类。静态初始化器同样有效,如果你想让映射不可修改,例如:
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);
}
我喜欢使用静态初始化“技术”,当我有一个抽象类的具体实现,它定义了一个初始化构造函数,但没有默认构造函数,但我希望我的子类有一个默认构造函数。
例如:
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...
}
}
这一个使用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));