Java map.get(key) - 自动执行 put(key) 并在 key 不存在时返回?
我厌倦了以下模式:
value = map.get(key);
if (value == null) {
value = new Object();
map.put(key, value);
}
这个示例仅涉及当您使用嵌套映射来表示多维结构时要编写的额外代码的表面。
我确信某个地方存在可以避免这种情况的东西,但我的谷歌搜索努力没有产生任何相关结果。有什么建议吗?
I am sick of the following pattern:
value = map.get(key);
if (value == null) {
value = new Object();
map.put(key, value);
}
This example only scratches the surface of the extra code to be written when you have nested maps to represent a multi-dimensional structure.
I'm sure something somewhere exists to avoid this, but my Googling efforts yielded nothing relevant. Any suggestions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
现有
Java 8 中的 and
返回
值,如果为 null,则插入给定值。因此,如果键不存在值,则返回 null 并插入给定值,否则返回现有值
如果您需要对值进行惰性评估,则可以使用
The
and from Java 8
has
which returns the existing value, and if that is null inserts given value. So if no value exists for key returns null and inserts the given value, otherwise returns existing value
If you need lazy evaluation of the value there is
Java 8 向 Map 添加了很好的方法: 计算, computeIfPresent< /a>, computeIfAbsent
要实现您所需要的:
Java 8 adds nice method to the Map: compute, computeIfPresent, computeIfAbsent
To achieve what you need:
这种模式的问题在于,您必须以某种方式定义在
get()
返回 null 时应使用的值。当然有图书馆,IIRC 也有一些较新的馆藏可以做到这一点,但不幸的是我不记得那些是哪些。
但是,您可以自己编写实用程序方法,前提是您有创建新值的标准方法。像这样的事情可能会起作用:
请注意,您要么必须抛出反射异常,要么在方法中处理它们。此外,这需要
valueClass
提供无参构造函数。或者,您可以简单地传递应使用的默认值。Java 8 更新
在其他答案中已经提到过,但为了完整起见,我也会在此处添加信息。
从 Java 8 开始,有默认方法computeIfAbsent(key,mappingFunction),它基本上做同样的事情,例如,如果值类是
BigDecimal
,它可能看起来像这样:该方法类似于上面定义的
safeGet(...)
但更灵活,可以直接在地图实例上使用并且经过更好的测试。因此,如果可能的话,我建议改用computeIfAbsent()。The problem with this pattern is that you'd have to somehow define the value that should be used in case the
get()
returns null.There certainly are libraries out there and IIRC there are also some newer collections that do that, but unfortunately I don't remember which those were.
However, you could write a utility method yourself, provided you have a standard way of creating the new values. Something like this might work:
Note that you'd either have to throw the reflection exceptions or handle them in the method. Additionally, this requires the
valueClass
to provide a no-argument constructor. Alternatively, you could simply pass the default value that should be used.Java 8 update
It has already been mentioned in other answers but for the sake of completeness I'll add the information here as well.
As of Java 8 there is the default method
computeIfAbsent(key, mappingFunction)
which basically does the same, e.g. if the value class wasBigDecimal
it could look like this:The implementation of that method is similar to the
safeGet(...)
defined above but more flexible, directly available at the map instance and better tested. So when possible I'd recommend usingcomputeIfAbsent()
instead.您可以使用 MutableMap 和 Eclipse Collections 中的
getIfAbsentPut()
,它返回映射到键或插入件给定值,如果没有值映射到键则返回给定值。您可以使用方法引用来创建一个新的
对象
:或者您可以直接创建一个新的
对象
:在第一个示例中,仅当存在时才会创建该对象没有值映射到键。
在第二个示例中,无论如何都会创建对象。
注意:我是 Eclipse Collections 的贡献者。
You can use MutableMap and
getIfAbsentPut()
from Eclipse Collections which returns the value mapped to the key or inserts the given value and returns the given value if no value is mapped to the key.You can either use a method reference to create a new
Object
:Or you can directly create a new
Object
:In the first example, the object will be created only if there is no value mapped to the key.
In the second example, the object will be created regardless.
Note: I am a contributor to Eclipse Collections.
如果在任何情况下您需要在地图中获取默认数据(如果它不存在)
javadocs
If in any case you need to get a default data in your map if it's not existing
javadocs
编辑:请注意,下面提到的功能已被长期弃用,并且 CacheBuilder。
Guava 库有一个“计算图”,请参阅MapMaker.makeComputingMap(函数)。
如果您多次需要该 Function,请将其提取到实用程序类中,然后像这样创建 Map(其中 MyFunctions.NEW_OBJECT 是静态 Function 实例):
EDIT : Note that the feature mentioned below is long deprecated, and a CacheBuilder should be used instead.
The Guava library has a "computing map", see MapMaker.makeComputingMap(Function).
If you need the Function several times, extract it into a utility class, and then create the Map like this (where
MyFunctions.NEW_OBJECT
is the static Function instance):也许我没有看到整个问题,但是使用继承或组合将此行为添加到 Map 对象怎么样?
Maybe I'm not seeing the whole problem, but how about using inheritance or composition to add this behavior to the Map object?