2012-04-15 19 views
2

我想用一个地图,就相当于ConcurrentMap创造的价值(我想的putIfAbsent方法是等效的),但不会强迫我创建预先提供对象。地图允许的putIfAbsent没有当键已经存在

例如,当我这样做:

m.putIfAbsent(key, new CyclingArray()); 

我最终可能会创建一个新的CyclingArray(无论是)对象罢了。

当然,我意识到我可以锁定整个地图,但这将击败ConcurrentMap的整个点。

在概念上可以像下面的工作?

m.putIfAbsent(key, new Callback<CyclingArray>() { 
    @Override 
    public CyclingArray provide() { 
     return new CyclingArray(); // only called if the key wasn't already present 
    }   
    } 

你知道任何库提供的地图:

  1. 提供一个“接口”之类的ConcurrentMap提供的一个,包括putIfAbsent方法。
  2. 没有只锁定我们将一起工作段(如ConcurrentHashMap实现不为例)
  3. 允许有选择地创造价值,当且仅当,关键是不存在的,因此躲闪无用的垃圾产生。
  4. 没有强迫我首先使用的containsKey然后的putIfAbsent因为如此,也不知何故违背了的putIfAbsent目的。

请注意,我不如果上面的例子可以用ConcurrentMap来完成(它不能据我所知)。

我在想有回调版本扩展ConcurrentHashMap和重载的putIfAbsent但遗憾的是ConcurrentHashMap内部使用最终类。

重新发明轮子之前,我想知道是否有任何地图已经提供了类似的功能。

回答

5

这是您正在寻找的常见用例,它被称为memoization。我想看看MapMaker

您将能够创建一个computingMap,把你的创造功能有:

ConcurrentMap<Key, CyclingArray> graphs = new MapMaker() 
     .concurrencyLevel(32) 
     .makeComputingMap(
      new Function<Key, CyclingArray>() { 
       public CyclingArray apply(Key key) { 
        return new CyclingArray(); // only called if the key wasn't already  
       }    
      }); 

这里Function才会被调用,如果Key不存在

我知道未来的Java计划有一个computeMap类型的接口将带有标准的Java,不幸的是,在这一点上,你将不得不委托给谷歌集合。

+0

+1 ...但我总是使用术语“memoization”来指代方法调用的* results *的缓存:* compute(17,24,59)*需要很长时间才能执行,并将计算结果存储在缓存并在缓存命中时重用。当我试图阻止不必要的对象创建时,我从未听说过使用“memoization”这个术语。在维基百科http://en.wikipedia.org/wiki/Memoization上,定义和例子与对象创建无关。我可能会弄错,但我觉得把它称为“memoization”有点奇怪:) – 2012-04-15 13:08:04

+0

只需要清楚一点:在这里使用回调来躲避对象创建本质上是围绕Java“功能”(让我们这么称呼它)工作。所以的确,我们最终可能会重复使用方法调用的结果,但在我的想法记忆中,我们一直都在使用方法调用的参数来快速计算密钥并将结果存储在缓存中(而不是动态编程,它通常预先缓存*所有可能的结果)。 – 2012-04-15 13:10:46

相关问题