Tony Stark
Tony Stark

Reputation: 25558

Java - is adding a key/value to a map within a map in 1 line of code possible?

I have HashMap 1, which contains 5 keys, all of which have Hashmaps as values. I want to add key/value pairs to these sub-Maps.

map1.get(subCategoryMap).put(newKey, newValue); 

My thinking is:

map1.get(subCategoryMap);

returns another map. I could split this line into two lines and have:

map2 = map1.get(subCategoryMap);
map2.put(newKey, newValue);

But I would MUCH prefer to do it in one step. Which is why I am trying

map1.get(subCategoryMap).put(newKey, newValue); 

This doesn't work (doesn't like .put() on an object). Is it possible to access the sub-Map and add to it in the same line of code like I am above, or do I need to split this into 2 lines?

Upvotes: 3

Views: 25690

Answers (8)

Nettogrof
Nettogrof

Reputation: 2136

You can use ((HashMap)map1.get(subCategoryMap)).put(newKey, newValue);

Also, if you are using Java 5 or Java 6, you can use generic to avoid the cast in HashMap

Upvotes: 0

Bill K
Bill K

Reputation: 62789

Just an aside (I'd make this a comment but I think it will be slightly long)...

It feels very good for a programmer to be able to get a single conceptual operation on one line. To the programmer (at the time) it feels more readable, logical and just feels right.

It is almost never a good thing. For one thing, later it will be harder to parse than two lines--even if your gut reaction now is that it is more readable. Also--the more operations on one line, the harder it is to debug.

For readability, I'd say the Generics solution is about as much as I'd put on a single line--for the casting solution I'd break it down into two lines; I'd also break it down into multiple lines if either of the parameters were operations instead of just simple variables.

I know a lot of people won't agree with this and to tell you the truth I tend to put quite a bit on one line at first, but what I've noticed is that at the first sign of trouble or any confusion, it makes my life easier to break everything down into separate statements with clearly named variables.

At least as important--in cases with nested collections, I will often wrap the collections in a different object as well. This would be interesting in your case--the call would become a little more clear.

dataHolder.put(category, newKey, newVale);

Hides the mechanics of the nesting of the collections (which otherwise can be complex to remember correctly and easy to screw up) and makes your intent much clearer.

This pattern of wrapping (Not extending but encapsulating) nested collections feels strange at first but I really suggest you just give it a try--it really cleans up a LOT of code, makes everything much safer adds to everybody's comprehension, changes a "Collection" to a business object (where you can place business methods--a refactoring you will appreciate almost immediately), and just generally helps your code all over.

Upvotes: 3

Fabian Steeg
Fabian Steeg

Reputation: 45744

Works fine if you use generics:

Map<String,Map<String,Integer>> map = new HashMap<String,Map<String,Integer>>();
map.put("Test", new HashMap<String,Integer>());
map.get("Test").put("Some", 1);

Upvotes: 0

cletus
cletus

Reputation: 625247

With generics you can:

Map<String, Map<String, String>> map1 = ...
map1.get(category).put(subcategory, value);

If the maps aren't generic:

Map map1 = ...
((Map)map1.get(category)).put(subcategory, value);

Upvotes: 15

erickson
erickson

Reputation: 269797

As long as map1 is declared something like Map<OuterKey, Map<InnerKey, MyValue>>, a one-liner will work. However, you need to be careful about what happens if subCategoryMap doesn't exist in map1—a one-liner will raise a NullPointerException.

Upvotes: 0

Powerlord
Powerlord

Reputation: 88806

If you use Generic collections, then your code should work as written. Otherwise, you need to add in the appropriate casts into your single line.

Upvotes: 0

Thomas Owens
Thomas Owens

Reputation: 116187

If you aren't using Generics, then a HashMap stores and retrieves the keys and values as Object, so you might need to cast, which would look something like this:

((HashMap)map1.get(subCategoryMap)).put(newKey, newValue);

However, it would be helpful if you provided more code.

Upvotes: 0

Andrew Duffy
Andrew Duffy

Reputation: 6938

((Map)map1.get(subCategoryMap)).put(newKey, newValue);

Or, use generics:

Map<X, Map<Y,Z>> map1;

...

map1.get(subCategoryMap).put(newKey, newValue);

However, both techniques will fail with NullPointerException if map1 doesn't contain a mapping for subCategoryMap.

Upvotes: 9

Related Questions