简体   繁体   English

Java - 是否可以在一行代码中向地图中的地图添加键/值?

[英]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. 我有HashMap 1,它包含5个键,所有键都有Hashmaps作为值。 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). 这不起作用(不喜欢对象上的.put())。 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? 是否可以访问子地图并在我上面的相同代码行中添加,或者我需要将其拆分为2行?

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);
((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 . 但是,如果map1不包含subCategoryMap的映射,则这两种技术都将失败并显示NullPointerException

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; 为了便于阅读,我认为Generics解决方案与我在单行上的解决方案差不多 - 对于铸造解决方案,我将其分解为两行; 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. 这种包装模式(不扩展但封装)嵌套的集合起初感觉很奇怪,但我真的建议你试一试 - 它真的清理了很多代码,使一切更安全,增加了每个人的理解,改变了一个“集合” “对于业务对象(您可以放置​​业务方法 - 几乎可以立即升级的重构),并且通常可以帮助您的代码。

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: 如果您没有使用Generics,那么HashMap会将键和值存储并检索为Object,因此您可能需要进行强制转换,如下所示:

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

However, it would be helpful if you provided more code. 但是,如果您提供更多代码,将会很有帮助。

If you use Generic collections, then your code should work as written. 如果您使用Generic集合,那么您的代码应该按照编写的方式工作。 Otherwise, you need to add in the appropriate casts into your single line. 否则,您需要将适当的强制转换添加到单行中。

As long as map1 is declared something like Map<OuterKey, Map<InnerKey, MyValue>> , a one-liner will work. 只要map1被声明为类似Map<OuterKey, Map<InnerKey, MyValue>> ,一行就可以了。 However, you need to be careful about what happens if subCategoryMap doesn't exist in map1 —a one-liner will raise a NullPointerException . 但是,你必须要小心,如果发生了什么subCategoryMap不存在map1 -a一个班轮将引发NullPointerException

You can use ((HashMap)map1.get(subCategoryMap)).put(newKey, newValue); 你可以使用((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 此外,如果您使用的是Java 5或Java 6,则可以使用泛型来避免在HashMap中进行HashMap

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

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

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