Java map.get(key) - 自动执行 put(key) 并在 key 不存在时返回?

发布于 2024-12-18 18:33:23 字数 236 浏览 1 评论 0原文

我厌倦了以下模式:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

雨的味道风的声音 2024-12-25 18:33:23

现有

java.util.concurrent.ConcurrentMap 

Java 8 中的 and

Java.util.Map

返回

putIfAbsent(K key, V value) 

值,如果为 null,则插入给定值。因此,如果键不存在值,则返回 null 并插入给定值,否则返回现有值

如果您需要对值进行惰性评估,则可以使用

computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)

The

java.util.concurrent.ConcurrentMap 

and from Java 8

Java.util.Map

has

putIfAbsent(K key, V value) 

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

computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
北陌 2024-12-25 18:33:23

Java 8 向 Map 添加了很好的方法: 计算, computeIfPresent< /a>, computeIfAbsent

要实现您所需要的:

Object existingOrCreated = map.computeIfAbsent(key, (k) -> new Object());

Java 8 adds nice method to the Map: compute, computeIfPresent, computeIfAbsent

To achieve what you need:

Object existingOrCreated = map.computeIfAbsent(key, (k) -> new Object());
尛丟丟 2024-12-25 18:33:23

这种模式的问题在于,您必须以某种方式定义在 get() 返回 null 时应使用的值。

当然有图书馆,IIRC 也有一些较新的馆藏可以做到这一点,但不幸的是我不记得那些是哪些。

但是,您可以自己编写实用程序方法,前提是您有创建新值的标准方法。像这样的事情可能会起作用:

public static <K, V> V safeGet(K key, Map<K,V> map, Class<V> valueClass) throws /*add exceptions*/ {
  V value = map.get(key);
  if( value == null ) {
    value = valueClass.newInstance();
    map.put( key, value );
  }   

  return value;
} 

请注意,您要么必须抛出反射异常,要么在方法中处理它们。此外,这需要 valueClass 提供无参构造函数。或者,您可以简单地传递应使用的默认值。

Java 8 更新

在其他答案中已经提到过,但为了完整起见,我也会在此处添加信息。

从 Java 8 开始,有默认方法computeIfAbsent(key,mappingFunction),它基本上做同样的事情,例如,如果值类是BigDecimal,它可能看起来像这样

BigDecimal value = map.computeIfAbsent(key, k -> new BigDecimal("123.456"));

:该方法类似于上面定义的 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:

public static <K, V> V safeGet(K key, Map<K,V> map, Class<V> valueClass) throws /*add exceptions*/ {
  V value = map.get(key);
  if( value == null ) {
    value = valueClass.newInstance();
    map.put( key, value );
  }   

  return value;
} 

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 was BigDecimal it could look like this:

BigDecimal value = map.computeIfAbsent(key, k -> new BigDecimal("123.456"));

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 using computeIfAbsent() instead.

瘫痪情歌 2024-12-25 18:33:23

您可以使用 MutableMapEclipse Collections 中的 getIfAbsentPut() ,它返回映射到键或插入件给定值,如果没有值映射到键则返回给定值。

您可以使用方法引用来创建一个新的对象

MutableMap<String, Object> map = Maps.mutable.empty();
Object value = map.getIfAbsentPut("key", Object::new);

或者您可以直接创建一个新的对象

MutableMap<String, Object> map = Maps.mutable.empty();    
Object value = map.getIfAbsentPut("key", new Object());

在第一个示例中,仅当存在时才会创建该对象没有值映射到键。

在第二个示例中,无论如何都会创建对象。

注意:我是 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:

MutableMap<String, Object> map = Maps.mutable.empty();
Object value = map.getIfAbsentPut("key", Object::new);

Or you can directly create a new Object:

MutableMap<String, Object> map = Maps.mutable.empty();    
Object value = map.getIfAbsentPut("key", 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.

╰◇生如夏花灿烂 2024-12-25 18:33:23

如果在任何情况下您需要在地图中获取默认数据(如果它不存在)

map.getOrDefault(key, defaultValue);

javadocs

If in any case you need to get a default data in your map if it's not existing

map.getOrDefault(key, defaultValue);

javadocs

娇纵 2024-12-25 18:33:23

编辑:请注意,下面提到的功能已被长期弃用,并且 CacheBuilder

Guava 库有一个“计算图”,请参阅MapMaker.makeComputingMap(函数)

Map<String, Object> map = new MapMaker().makeComputingMap(
    new Function<String, Object>() {
      public String apply(Stringt) {
        return new Object();
      }
  });

如果您多次需要该 Function,请将其提取到实用程序类中,然后像这样创建 Map(其中 MyFunctions.NEW_OBJECT 是静态 Function 实例):

Map<String, Object> map = new MapMaker()
    .makeComputingMap(MyFunctions.NEW_OBJECT);

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

Map<String, Object> map = new MapMaker().makeComputingMap(
    new Function<String, Object>() {
      public String apply(Stringt) {
        return new Object();
      }
  });

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<String, Object> map = new MapMaker()
    .makeComputingMap(MyFunctions.NEW_OBJECT);
我为君王 2024-12-25 18:33:23

也许我没有看到整个问题,但是使用继承或组合将此行为添加到 Map 对象怎么样?

Maybe I'm not seeing the whole problem, but how about using inheritance or composition to add this behavior to the Map object?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文