在 Java 中是否有编写地图文字样式的最佳实践?

发布于 2024-09-25 14:37:03 字数 347 浏览 8 评论 0原文

简而言之,如果您想在 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 ,
    //...
} ;

是否有一个 Class 或任何预设的 Object 你可以用它来编写这样的数据结构吗?

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,

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

一生独一 2024-10-02 14:37:03

我喜欢这样做:

Map map = new HashMap() {{
    put("foo", "bar");
    put(123, 456);
}};

双 {{ }} 是实例初始化块。它们有点不寻常,但很有用。不需要图书馆或助手。

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.

稚然 2024-10-02 14:37:03

不,Java 没有地图文字。最接近的方法是使用 Google Collections 的 不可变映射

Map<K,V> CONSTANTS = ImmutableMap.of(
    NAME_1, VALUE_1,
    NAME_2, VALUE_2
    //etc.
  );

No, Java doesn't have a map literal. The closest you'll come to this is using Google Collections' ImmutableMap:

Map<K,V> CONSTANTS = ImmutableMap.of(
    NAME_1, VALUE_1,
    NAME_2, VALUE_2
    //etc.
  );
西瓜 2024-10-02 14:37:03

常数?我会使用 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;
    }
}

例如NAME_2的值可以通过如下方式获得:

String name2value = Constants.NAME_2.value();

只给枚举一个更合理的名称,例如SettingsDefaults等,无论那些名称/值对实际上表示。

Constants? I'd use an 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:

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 actually represent.

忆依然 2024-10-02 14:37:03

抱歉,我是一个修补匠:-) 这是一种更干净的方法。

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

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;
    }
}
〆凄凉。 2024-10-02 14:37:03

您可以自己编写一个快速帮助函数:

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

请注意,上面的代码不会阻止您覆盖同名常量,在列表中的多个位置使用 CONST_1 将得到最终的CONST_1 的值出现。

用法是这样的:

Map<String,Double> constants = ImmutableMap(
    "CONST_0", 1.0,
    "CONST_1", 2.0
);

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.

Usage is something like:

Map<String,Double> constants = ImmutableMap(
    "CONST_0", 1.0,
    "CONST_1", 2.0
);
街角卖回忆 2024-10-02 14:37:03

从 Java 9 开始,您可以开箱即用地创建不可修改的映射 -

Map<String, String> emptymap = Map.of();
Map<String, String> map = Map.of("key1", "val1"); 

有支持最多 10 个密钥对的变体。
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html#of()

这也受支持 https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html#ofEntries(java.util.Map.Entry.. .)

 import static java.util.Map.entry;

 Map<Integer,String> map = Map.ofEntries(
     entry(1, "a"),
     entry(2, "b"),
     entry(3, "c"),
     ...
     entry(26, "z"));

Since Java 9, you can create unmodifiable maps out of the box -

Map<String, String> emptymap = Map.of();
Map<String, String> map = Map.of("key1", "val1"); 

there are variants supporting upto 10 keypairs.
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html#of()

This is also supported https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html#ofEntries(java.util.Map.Entry...)

 import static java.util.Map.entry;

 Map<Integer,String> map = Map.ofEntries(
     entry(1, "a"),
     entry(2, "b"),
     entry(3, "c"),
     ...
     entry(26, "z"));
尴尬癌患者 2024-10-02 14:37:03

这是另一种方法,最适合不会改变的地图:

public class Whatever {
    private static Map<String,String> map = new HashMap<String,String>();

    static {
        map.put("A", "Apple");
        map.put("B", "Banana");
        // etc
    }
}

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
    }
}
月下伊人醉 2024-10-02 14:37:03

Java7 假设实现以下语法:

Map<String, String> = {
    "key1": "value",
    "key2": "value",
    "key3": "value",
    "key4": "value"
};

但是现在您被迫使用 Jorn 或 Tony Ennis 提出的解决方案。

Java7 suppose to implement following syntax:

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.

没有心的人 2024-10-02 14:37:03

好吧,随着乔恩的进步,我似乎根本无法改变地图,无论是内部还是外部。也许不太可读,但如果您需要地图不可修改,我认为这更好。

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

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.

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");
    }
}
药祭#氼 2024-10-02 14:37:03

我喜欢在同一行进行声明和初始化。我已经使用这个方便的小实用程序这么长时间了,它基本上我的“地图文字”,直到它们在语言中“正确”完成之前,我将继续像这样使用它: )

很高兴在这里分享。

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

}

I like to do the declaration and initialization on the same line. I've used this handy little utility for so long it basically is my "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;
    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文