Correct way to initialize HashMap and can HashMap hold different value types?
Solution 1
It really depends on what kind of type safety you need. The non-generic way of doing it is best done as:
Map x = new HashMap();
Note that x
is typed as a Map
. this makes it much easier to change implementations (to a TreeMap
or a LinkedHashMap
) in the future.
You can use generics to ensure a certain level of type safety:
Map<String, Object> x = new HashMap<String, Object>();
In Java 7 and later you can do
Map<String, Object> x = new HashMap<>();
The above, while more verbose, avoids compiler warnings. In this case the content of the HashMap
can be any Object
, so that can be Integer
, int[]
, etc. which is what you are doing.
If you are still using Java 6, Guava Libraries (although it is easy enough to do yourself) has a method called newHashMap()
which avoids the need to duplicate the generic typing information when you do a new
. It infers the type from the variable declaration (this is a Java feature not available on constructors prior to Java 7).
By the way, when you add an int or other primitive, Java is autoboxing it. That means that the code is equivalent to:
x.put("one", Integer.valueOf(1));
You can certainly put a HashMap
as a value in another HashMap
, but I think there are issues if you do it recursively (that is put the HashMap
as a value in itself).
Solution 2
This is a change made with Java 1.5. What you list first is the old way, the second is the new way.
By using HashMap you can do things like:
HashMap<String, Doohickey> ourMap = new HashMap<String, Doohickey>();
....
Doohickey result = ourMap.get("bob");
If you didn't have the types on the map, you'd have to do this:
Doohickey result = (Doohickey) ourMap.get("bob");
It's really very useful. It helps you catch bugs and avoid writing all sorts of extra casts. It was one of my favorite features of 1.5 (and newer).
You can still put multiple things in the map, just specify it as Map, then you can put any object in (a String, another Map, and Integer, and three MyObjects if you are so inclined).
Solution 3
Eclipse is recommending that you declare the type of the HashMap because that enforces some type safety. Of course, it sounds like you're trying to avoid type safety from your second part.
If you want to do the latter, try declaring map as HashMap<String,Object>
.
Solution 4
The way you're writing it is equivalent to
HashMap<Object, Object> map = new HashMap<Object, Object>();
What goes inside the brackets is you communicating to the compiler what you're going to put in the HashMap so that it can do error checking for you. If Object, Object is what you actually want (probably not) you should explicitly declare it. In general you should be as explicit as you can with the declaration to facilitate error checking by the compiler. What you've described should probably be declared like this:
HashMap<String, Object> map = new HashMap<String, Object>();
That way you at least declare that your keys are going to be strings, but your values can be anything. Just remember to use a cast when you get a value back out.
Solution 5
The 2nd one is using generics which came in with Java 1.5. It will reduce the number of casts in your code & can help you catch errors at compiletime instead of runtime. That said, it depends on what you are coding. A quick & dirty map to hold a few objects of various types doesn't need generics. But if the map is holding objects all descending from a type other than Object, it can be worth it.
The prior poster is incorrect about the array in a map. An array is actually an object, so it is a valid value.
Map<String,Object> map = new HashMap<String,Object>();
map.put("one",1); // autoboxed to an object
map.put("two", new int[]{1,2} ); // array of ints is an object
map.put("three","hello"); // string is an object
Also, since HashMap is an object, it can also be a value in a HashMap.
Tony Stark
Updated on September 19, 2020Comments
-
Tony Stark almost 4 years
So I have two questions about
HashMap
s in Java:What is the correct way to initialize a
HashMap
? I think it might be best in my situation to use:HashMap x = new HashMap();
But Eclipse keeps suggesting that I use:
HashMap<something, something> map = new HashMap();
Which is better?
Can a
HashMap
hold different types of objects/data types as values? For example, would this work and be OK:map.put("one", 1); map.put("two", {1, 2}); map.put("three", "hello");
In the first
put()
, I want anint
as a value, in the second anint[]
, and third a string. Is this okay to do in Java withHashMap
s? Also, is it okay to store aHashMap
as a value within aHashMap
?
-
Tony Stark almost 15 yearsis an int considered an object..?
-
ChssPly76 almost 15 yearsYou've had me up until the last paragraph. "lists with little 'l'" are called arrays; and they are most definitely objects in Java.
-
Tony Stark almost 15 yearsYou mention that to put multiple things in the map, I should just specify it as a Map. Why couldn't I use HashMap?
-
Paul Tomblin almost 15 yearsautoboxing will convert int[] into an Object.
-
ChssPly76 almost 15 yearsint[] is already an Object; surely you meant single
int
variable -
Tony Stark almost 15 yearswhat is the difference between making a HashMap<String, Object> map = new... and Map<String, Object> map = new...? Or do they make the same thing?
-
Yishai almost 15 yearsIn Java 5+, the compiler will do that for you.
-
ColinD almost 15 yearsIt'll work in Java 5, which he's using since he's getting warnings about not having parameterized the map, with autoboxing.
-
Yishai almost 15 yearsThey make the same thing, it is just that your reference is typed as a Map (the interface) instead of the HashMap (the implementation) so that the implementation can be easily changed without affecting more than one line of code.
-
Jedihomer Townend almost 15 years@ChssPly76: "arrays". That's the term. I couldn't remember it and went with my best guess at the moment. Thanks.
-
Jedihomer Townend almost 15 years@hatorade: What I meant was just use Map instead of Map<String, Integer>. If you leave off the types the map will hold, you get basically Map<Object, Object>. You can use any kind of Map you'd like (HashMap, TreeMap, MyCustomMap, etc.).
-
Mick Belker - Pseudonym over 3 yearsThis is the most elegant way for HashMap initializers with a handfull of elements, without using double brace initialization, and even without any additional package dependency!
-
Mick Belker - Pseudonym over 3 yearsLook at the answer of Basil. Map.of() is the best way for a static list of few elements, having initializer in call.