是否有在 Java 中编写地图文字样式的最佳实践?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3798083/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a best practice for writing maps literal style in Java?
提问by FK82
In short, if you want to write a map of e.g. constants in Java, which in e.g. Python and Javascript you would write as a literal,
简而言之,如果您想在 Java 中编写例如常量的映射,例如在 Python 和 Javascript 中,您可以将其写为文字,
T<String,String> CONSTANTS =
{
"CONSTANT_NAME_0": CONSTANT_VALUE_0 ,
"CONSTANT_NAME_1": CONSTANT_VALUE_1 ,
"CONSTANT_NAME_2": CONSTANT_VALUE_2 ,
//...
} ;
is there a Class
or any preset Object
that you can use for writing a data structure like that?
是否有Class
任何预设Object
可用于编写这样的数据结构?
采纳答案by BalusC
Constants? I'd use an enum.
常数? 我会使用enum。
public enum Constants {
NAME_1("Value1"),
NAME_2("Value2"),
NAME_3("Value3");
private String value;
Constants(String value) {
this.value = value;
}
public String value() {
return value;
}
}
Value for e.g. NAME_2
can be obtained as follows:
eg 的值NAME_2
可以通过以下方式获得:
String name2value = Constants.NAME_2.value();
Only give the enum a bit more sensible name, e.g. Settings
, Defaults
, etc, whatever those name/value pairs actuallyrepresent.
只给枚举一点更明智的名称,例如Settings
,Defaults
等,无论这些名称/值对实际代表。
回答by xpmatteo
I like to do it this way:
我喜欢这样做:
Map map = new HashMap() {{
put("foo", "bar");
put(123, 456);
}};
The double {{ }} are an instance initialization block. They are a bit unusual but they are useful. No need for libraries or helpers.
double {{ }} 是一个实例初始化块。它们有点不寻常,但很有用。不需要图书馆或助手。
回答by Jorn
No, Java doesn't have a map literal. The closest you'll come to this is using Google Collections' ImmutableMap:
不,Java 没有地图文字。您最接近的是使用 Google Collections 的ImmutableMap:
Map<K,V> CONSTANTS = ImmutableMap.of(
NAME_1, VALUE_1,
NAME_2, VALUE_2
//etc.
);
回答by Tony Ennis
Sorry, I'm a tinkerer :-) Here's a somewhat cleaner way.
抱歉,我是个修补匠 :-) 这是一种更简洁的方法。
public class MapTest {
private static Map<String, String> map;
static {
Map<String, String> tmpMap = new HashMap<String, String>();
tmpMap.put("A", "Apple");
tmpMap.put("B", "Banana");
// etc
map = Collections.unmodifiableMap(tmpMap);
}
public Map<String, String> getMap() {
return map;
}
}
回答by Mark Elliot
You can write yourself a quick helper function:
你可以自己写一个快速的辅助函数:
@SuppressWarnings("unchecked")
public static <K,V> Map<K,V> ImmutableMap(Object... keyValPair){
Map<K,V> map = new HashMap<K,V>();
if(keyValPair.length % 2 != 0){
throw new IllegalArgumentException("Keys and values must be pairs.");
}
for(int i = 0; i < keyValPair.length; i += 2){
map.put((K) keyValPair[i], (V) keyValPair[i+1]);
}
return Collections.unmodifiableMap(map);
}
Note the code above isn't going to stop you from overwriting constants of the same name, using CONST_1
multiple places in your list will result in the final CONST_1
's value appearing.
请注意,上面的代码不会阻止您覆盖同名的常量,CONST_1
在列表中使用多个位置将导致CONST_1
出现final的值。
Usage is something like:
用法类似于:
Map<String,Double> constants = ImmutableMap(
"CONST_0", 1.0,
"CONST_1", 2.0
);
回答by cobbzilla
I like to do the declaration and initialization on the same line. I've used this handy little utility for so long it basically ismy "map literal" and until they're done "right" in the languange, I'm gonna continue on using it like that :)
我喜欢在同一行进行声明和初始化。我已经使用这个方便的小实用程序很长时间了,它基本上是我的“地图文字”,直到它们在语言中“正确”完成,我将继续像这样使用它:)
Happy to share it here.
很高兴在这里分享。
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* A handy utility for creating and initializing Maps in a single statement.
* @author Jonathan Cobb. This source code is in the Public Domain.
*/
public class MapBuilder {
/**
* Most common create/init case. Usage:
*
* Map<String, Boolean> myPremadeMap = MapBuilder.build(new Object[][]{
* { "a", true }, { "b", false }, { "c", true }, { "d", true },
* { "e", "yes, still dangerous but at least it's not an anonymous class" }
* });
*
* If your keys and values are of the same type, it will even be typesafe:
* Map<String, String> someProperties = MapBuilder.build(new String[][]{
* {"propA", "valueA" }, { "propB", "valueB" }
* });
*
* @param values [x][2] array. items at [x][0] are keys and [x][1] are values.
* @return a LinkedHashMap (to preserve order of declaration) with the "values" mappings
*/
public static <K,V> Map<K,V> build(Object[][] values) {
return build(new LinkedHashMap<K,V>(), values);
}
/**
* Usage:
* Map<K,V> myMap = MapBuilder.build(new MyMapClass(options),
* new Object[][]{ {k,v}, {k,v}, ... });
* @param map add key/value pairs to this map
* @return the map passed in, now containing new "values" mappings
*/
public static <K,V> Map<K,V> build(Map<K,V> map, Object[][] values) {
for (Object[] value : values) {
map.put((K) value[0], (V) value[1]);
}
return map;
}
/** Same as above, for single-value maps */
public static <K,V> Map<K,V> build(Map<K,V> map, K key, V value) {
return build(map, new Object[][]{{key,value}});
}
/**
* Usage:
* Map<K,V> myMap = MapBuilder.build(MyMapClass.class, new Object[][]{ {k,v}, {k,v}, ... });
* @param mapClass a Class that implements Map
* @return the map passed in, now containing new "values" mappings
*/
public static <K,V> Map<K,V> build(Class<? extends Map<K,V>> mapClass, Object[][] values) {
final Map<K,V> map;
try { map = mapClass.newInstance(); } catch (Exception e) {
throw new IllegalStateException("Couldn't create new instance of class: "+mapClass.getName(), e);
}
return build(map, values);
}
/** Usage: Map<K,V> myMap = MapBuilder.build(key, value); */
public static <K,V> Map build(K key, V value) {
Map<K,V> map = new HashMap<>();
map.put(key, value);
return map;
}
}
回答by Tony Ennis
Ok, with Jorn's improvement I can't seem to change the map at all, internally or externally. Perhaps not quite as readable, but if you need the map to be unmodifiable I think this is better.
好吧,随着 Jorn 的改进,我似乎根本无法在内部或外部更改地图。也许不太可读,但如果您需要地图不可修改,我认为这更好。
public class MapTest {
private static Map<String, String> map = initMap();
private static Map<String, String> initMap() {
Map<String, String> map = new HashMap<String, String>();
map.put("A", "Apple");
map.put("B", "Banana");
// etc
return Collections.unmodifiableMap(map);
}
public Map<String, String> getMap() {
return map;
}
public static void main(String[] args) {
MapTest m = new MapTest();
System.out.println(m.getMap().get("A"));
m.getMap().put("this", "that");
}
}
回答by Tony Ennis
Here's another way, best suited for maps that won't be changing:
这是另一种方式,最适合不会改变的地图:
public class Whatever {
private static Map<String,String> map = new HashMap<String,String>();
static {
map.put("A", "Apple");
map.put("B", "Banana");
// etc
}
}
回答by Crozin
Java7 suppose to implement following syntax:
Java7 假设实现以下语法:
Map<String, String> = {
"key1": "value",
"key2": "value",
"key3": "value",
"key4": "value"
};
However now you're forced to use solutions proposed by Jorn or Tony Ennis.
但是,现在您不得不使用 Jorn 或 Tony Ennis 提出的解决方案。