繁体   English   中英

在Java中,我可以声明一个HashMap常量吗?

[英]In Java, can I declare a HashMap constant?

我正在写一个简单的程序,将一个数字转换成一个代表该数字的单词(13 =>“十三”)。

我意识到我可以用这样的常量String数组得到一些单词:

private static final String[] tensNames = {"", " ten", " twenty", " thirty", " forty", " fifty", " sixty", " seventy", " eighty", " ninety" };

...并使用索引访问它,但我想尝试使用这样的HashMap:

final HashMap<Integer, String> tensNumberConversion = new HashMap<Integer, String>();
    tensNumberConversion.put(2, "twenty");
    tensNumberConversion.put(3, "thirty");
    tensNumberConversion.put(4, "forty");
    tensNumberConversion.put(5, "fifty");
    tensNumberConversion.put(6, "sixty");
    tensNumberConversion.put(7, "seventy");
    tensNumberConversion.put(8, "eighty");
    tensNumberConversion.put(9, "ninety");

我被老师指示制作这些常数。 HashMap可以是常量吗? 作为一个新手,尚不完全清楚术语“常数”,“静态”和“最终”是如何相关的,以及究竟是什么使它成为一个常数。 (单独静止?最后一个人?静态决赛一起?)。

我尝试将其设为私有静态最终Hashmap,但IntelliJ给了我一个错误(修改符'私有'这里不允许...对于'静态'相同)。

但是,它确实从我的终端编译没有错误。 如果HashMap可以是常量,这是声明一个的正确方法吗? 谢谢!

是的,它可以是一个常数。 您应该如下声明HashMap实例:

class <class name> {
    private static final HashMap<Integer, String> tensNumberConversion = new HashMap<>();

    static {
        tensNumberConversion.put(2, "twenty");
        tensNumberConversion.put(3, "thirty");
        tensNumberConversion.put(4, "forty");
        tensNumberConversion.put(5, "fifty");
        tensNumberConversion.put(6, "sixty");
        tensNumberConversion.put(7, "seventy");
        tensNumberConversion.put(8, "eighty");
        tensNumberConversion.put(9, "ninety");
    }
}

但是,这只是一个不变的参考。 虽然您无法将tensNumberConversion重新分配给其他内容,但您仍可以在运行时更改地图的内容:

tensNumberConversion = new HashMap<>(); // won't compile
tensNumberConversion.put(9, "one"); // succeeds

如果您希望地图的内容也是常量,则应将HashMap包装到不可修改的地图中:

class <class name> {
    private static final Map<Integer, String> tensNumberConversion = initMap();

    private static Map<Integer, String> initMap() {
        Map<Integer, String> map = new HashMap<>();
        map.put(2, "twenty");
        map.put(3, "thirty");
        map.put(4, "forty");
        map.put(5, "fifty");
        map.put(6, "sixty");
        map.put(7, "seventy");
        map.put(8, "eighty");
        map.put(9, "ninety");
        return Collections.unmodifiableMap(map);
    }
}

这里有两个方面:

  • 您有一个包含对地图的引用的变量。 您只需将该变量声明为final ; 并且,您无法将变量更改为指向另一个参考。
  • 但这并不妨碍您更改引用指向的对象的状态 因此,即使您拥有最终的Map对象,您仍然可以在该Map上调用put / remove / ...方法。

所以,为了得到一个真正的“恒定”地图,你可以做到这一点:

首先,创建一个包含所有所需值的普通地图。

然后使用Collections.unmodifiableMap()创建一个无法再更改的地图。

需要注意的一件事是:你必须确保你没有泄漏对原始地图对象的引用,因为不可变地图只是该初始地图的包装。 例如,你可以用一个小帮手方法做到这一点。

如果你问:是否有办法以特殊的“文字形式”(如数组)写下地图声明 - 没有。 那么,您可以更改该辅助方法以将Object ...作为参数; 然后你会经历这些参数,一个是数字,下一个是一个字符串,并使用它来填充地图。 因此,您可以使用单个值序列调用该方法。 但可能不值得努力......

快速更新:Java9添加了各种静态帮助器方法,允许您以某种方式“文字”方式写下地图,例如,请参见此处

只是一个BTW,使用Java 9 Map接口中静态方法来创建具有一些条目的不可变映射,例如:

Map<String,String> m = Map.of("k1", "v1",
                              "K2", "v2");

或者如果需要超过10个条目:

import static java.util.Map.entry;
Map<String, String> m = Map.ofEntries(
    entry("k1", "v1"), entry("k2", "v2"), …);

我在某种程度上错过了在这里直接初始化HashMap最简单的形式

private static final Map<Integer, String> tensNumberConversion_internal = new HashMap<Integer, String>()
{
    {
        put(2, "twenty");
        put(3, "thirty");
        put(4, "forty");
        put(5, "fifty");
        put(6, "sixty");
        put(7, "seventy");
        put(8, "eighty");
        put(9, "ninety");
    };
};

至于使它不变,你已经从接受的答案中得到了Collections.unmodifiableMap

public static final Map<Integer, String> tensNumberConversion = Collections.unmodifiableMap(tensNumberConversion_internal);

它们必须按照这个顺序创建;)

您可以使用继承从HashMap继承新类,然后重写HashMap.put()方法以显示一些适当的失败消息,而不是使用堆肥来实现常量HashMap。

class MyMap extends java.util.HashMap{
@Override
public V put (K key, V value){
System.out.println("Operation Not Supported");
return null;
}
}

请注意,这不是唯一的方法,而是可能的众多方法之一

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM