我厌倦了以下模式:
value = map.get(key);
if (value == null) {
value = new Object();
map.put(key, value);
}
当您使用嵌套地图来表示多维结构时,此示例仅会覆盖要写入的额外代码的表面。
我确信存在某些地方可以避免这种情况,但我的谷歌搜索努力没有产生任何相关性。有什么建议吗?
答案 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添加了一个不错的方法:compute,computeIfPresent,computeIfAbsent
实现您的需求:
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 Collections和getIfAbsentPut()
,它返回映射到键的值或插入给定值,如果没有值映射到键,则返回给定值。
您可以使用方法参考来创建新的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)
答案 6 :(得分:0)
也许我没有看到整个问题,但是如何使用继承或组合将此行为添加到Map对象?