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

时间:2011-11-30 22:42:45

标签: java dictionary get null put

我厌倦了以下模式:

value = map.get(key);
if (value == null) {
    value = new Object();
    map.put(key, value);
}

当您使用嵌套地图来表示多维结构时,此示例仅会覆盖要写入的额外代码的表面。

我确信存在某些地方可以避免这种情况,但我的谷歌搜索努力没有产生任何相关性。有什么建议吗?

7 个答案:

答案 0 :(得分:38)

java.util.concurrent.ConcurrentMap 

和Java 8

Java.util.Map

putIfAbsent(K key, V value) 

返回映射到key的值或插入给定值,如果没有为键映射值,则返回null。

如果您需要对值进行延迟评估,则

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

答案 1 :(得分:25)

Java 8为Map添加了一个不错的方法:computecomputeIfPresentcomputeIfAbsent

实现您的需求:

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

答案 2 :(得分:3)

此模式的问题在于,您必须以某种方式定义在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提供无参数构造函数。或者,您可以简单地传递应该使用的默认值。

答案 3 :(得分:3)

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

您可以使用方法参考来创建新的Object

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

或者您可以直接创建新的Object

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

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

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

注意:我是Eclipse Collections的撰稿人。

答案 4 :(得分:1)

编辑:请注意,下面提到的功能已被弃用,而应使用CacheBuilder代替。

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

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

答案 5 :(得分:1)

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

map.getOrDefault(key, defaultValue);

javadocs

答案 6 :(得分:0)

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