I am writing a simple program to convert a number to a word representing that number (13 => "thirteen").
I realize I could get some of the words with a constant String array like this:
private static final String[] tensNames = {"", " ten", " twenty", " thirty", " forty", " fifty", " sixty", " seventy", " eighty", " ninety" };
...and access it with the index, but I wanted to try it with a HashMap like this:
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");
I was instructed by a teacher to make these constants. Can the HashMap be a constant? As a newbie, it wasn't totally clear how the terms "constant" and "static" and "final" are related, and what exactly makes a constant. (static alone? final alone? static final together?).
I tried making it private static final Hashmap but IntelliJ gave me an error (modifier 'private' not allowed here...same for 'static').
However, it does compile from my terminal with no errors. If a HashMap can be a constant, is this the right way to declare one? Thanks!
The Static Initializer for a Static HashMap We can also initialize the map using the double-brace syntax: Map<String, String> doubleBraceMap = new HashMap<String, String>() {{ put("key1", "value1"); put("key2", "value2"); }};
To turn an ordinary variable into a constant, you have to use the keyword "final." As a rule, we write constants in capital letters to differentiate them from ordinary variables. If you try to change the constant in the program, javac (the Java Compiler) sends an error message.
Yes, it can be a constant. You should declare your HashMap
instance as follows:
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"); } }
However, this is only a constant reference. While you can not reassign tensNumberConversion
to something else, you still can change the contents of your map later at runtime:
tensNumberConversion = new HashMap<>(); // won't compile tensNumberConversion.put(9, "one"); // succeeds
If you want the contents of your map constant too, you should wrap the HashMap
into an unmodifiable map:
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); } }
There are two aspects here:
So, in order to come to a real "constant" Map, you do go for this:
First you create an ordinary map containing all the desired values.
Then you use Collections.unmodifiableMap()
in order to create a map that can't be changed any more.
The one thing to pay attention to: you have to make sure that you are not leaking a reference to the original map object as that immutable map is just a wrapper around that initial map. You could do that in a little helper method for example.
If you are asking: is there a way to write down a map declaration in a special "literal form" (like for arrays) - there isn't. Well, you can change that helper method to take Object ...
as parameter; and then you would go through those parameters, one is a number, next one a string, and use that to fill the map. So you could then invoke the method with a single sequence of values. But probably not worth the effort ...
A quick update: Java9 added various static helper methods that allow you write down maps in a somehow "literal" way, see here for example.
Just a BTW, with Java 9 there are static methods in the Map
interface to create immutable Maps with some number of entries like:
Map<String,String> m = Map.of("k1", "v1",
"K2", "v2");
Or if more than 10 entries are needed:
import static java.util.Map.entry;
Map<String, String> m = Map.ofEntries(
entry("k1", "v1"), entry("k2", "v2"), …);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With