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

Sri*_*bat 54 java null dictionary get put

我厌倦了以下模式:

value = map.get(key);
if (value == null) {
    value = new Object();
    map.put(key, value);
}
Run Code Online (Sandbox Code Playgroud)

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

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

Rog*_*sjö 48

java.util.concurrent.ConcurrentMap 
Run Code Online (Sandbox Code Playgroud)

并从Java 8

Java.util.Map
Run Code Online (Sandbox Code Playgroud)

具有

putIfAbsent(K key, V value) 
Run Code Online (Sandbox Code Playgroud)

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

如果你需要延迟评估值

computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这会强制您创建新对象,即使地图中已有一个对象也是如此.如果你真的只创建一个`new Object()`,这可能是微不足道的. (6认同)
  • 返回:与指定键关联的先前值,如果没有键的映射,则返回null (5认同)
  • java.util.Map有来自JDK 8的putIfAbsent,而不仅仅是ConcurrentMap. (3认同)
  • 它不起作用是价值本身应该是一个集合。因为我想要的是添加一个空集合并返回它,以便我可以将项目添加到该集合中。 (2认同)

iTa*_*ake 34

Java 8为Map添加了很好的方法:compute,computeIfPresent,computeIfAbsent

为了达到你的需求:

Object existingOrCreated = map.computeIfAbsent(key, (k) -> new Object());
Run Code Online (Sandbox Code Playgroud)

  • 公认的答案指向相同的方法。但是,此答案更加清楚。 (3认同)

Tho*_*mas 6

这种模式的问题在于,您必须以某种方式定义在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;
} 
Run Code Online (Sandbox Code Playgroud)

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

Java 8 更新

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

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

BigDecimal value = map.computeIfAbsent(key, k -> new BigDecimal("123.456"));
Run Code Online (Sandbox Code Playgroud)

该方法的实现与safeGet(...)上面定义的类似,但更灵活,可直接在地图实例上使用并且经过更好的测试。因此,如果可能,我建议computeIfAbsent()改用。