映射允许putIfAbsent而不创建密钥已存在时的值

Ced*_*tin 2 java concurrency map garbage

我想使用一个相当于ConcurrentMap(我想要相当于putIfAbsent方法)的地图,但这不会强迫我事先创建对象.

例如,当我这样做时:

m.putIfAbsent( key, new CyclingArray() );
Run Code Online (Sandbox Code Playgroud)

我可能最终创建一个新的CyclingArray(无论是什么)对象.

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

在概念上可以做以下工作吗?

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

你知道任何提供地图的图书馆:

  1. 提供一个类似ConcurrentMap提供的"接口",包括一个putIfAbsent方法.
  2. 只锁定我们将要使用的段(例如,ConcurrentHashMap实现)
  3. 当且仅当密钥不存在时才允许可选地创建值,从而避免无用的垃圾生成.
  4. 不会强迫我首先使用containsKey然后使用putIfAbsent,因为这也会以某种方式违背putIfAbsent的目的.

请注意,我不是在问上面的例子是否可以使用ConcurrentMap(它不能是AFAIK).

我正在考虑使用回调版本扩展ConcurrentHashMap和重载putIfAbsent,但遗憾的是ConcurrentHashMap内部使用了最终的Segment类.

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

Joh*_*int 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    
                }              
           });
Run Code Online (Sandbox Code Playgroud)

Function只有在Key不存在的情况下才会调用

我确实知道Java中的未来计划有一个带有标准Java的computeMap类型接口,不幸的是,此时你必须委托google-collections.