Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 具有良好性能的多重映射_Java_Performance_Multimap - Fatal编程技术网

Java 具有良好性能的多重映射

Java 具有良好性能的多重映射,java,performance,multimap,Java,Performance,Multimap,在我的代码中,我有一个在几秒钟内被大量使用的映射。最初我有一个树形图,但当测试9000个条目时,我看到我的旧处理器融化了。这需要扩大规模。所以我转向HashMap,性能非常好 现在我正在改变我的设计,正在寻找一个多重地图。但是,我担心get()端的性能会受到影响,因为它必须在所述的大映射上迭代,以找出匹配的键,并且当多次调用甚至同步时,它看起来会很慢 是否有一个好的多重映射可以处理如此大的值并具有很好的性能?在这个应用程序中,性能是至关重要的,因为可能有许多单独的大型映射处理非常大的工作负载,这

在我的代码中,我有一个在几秒钟内被大量使用的映射。最初我有一个树形图,但当测试9000个条目时,我看到我的旧处理器融化了。这需要扩大规模。所以我转向HashMap,性能非常好

现在我正在改变我的设计,正在寻找一个多重地图。但是,我担心
get()
端的性能会受到影响,因为它必须在所述的大映射上迭代,以找出匹配的键,并且当多次调用甚至同步时,它看起来会很慢

是否有一个好的多重映射可以处理如此大的值并具有很好的性能?在这个应用程序中,性能是至关重要的,因为可能有许多单独的大型映射处理非常大的工作负载,这使得“小”的性能损失成为非常大的问题


如果它可以被提取出来单独工作而没有任何依赖性,则会获得额外的积分

在我的一个问题中向我推荐的是Apache Commons MultiMap:

它是免费软件,所以您至少可以让源代码查看它,并且根据您的许可证情况,您可以修改它或单独使用它

它在内部使用ArrayList,但我想您可能可以将其更改为使用HashSet或其他东西。我将研究
createCollection(Collection coll)
方法

更新:事实上,番石榴的HashMultiMap似乎已经是我所说的了:


我查看了源代码,似乎每个值集合实际上都有一个哈希集作为后盾。

选择在很大程度上取决于您想要做什么。有许多数据结构,其中一些在特定领域优于其他数据结构,反之亦然

我可以向你推荐潜在的候选人。如果完全读取,ImmutableMultiMap可能非常适合

如果您需要并发读/写,那么我将实现自己的multimap,可能使用ConcurrentHashMap和ConcurrentSkipListSet(您需要小心,因为使用非阻塞数据结构以这种方式创建的同步multimap和multimap之间的语义不同)。如果您使用ConcurrentSkipListSet,那么就可以使用二进制搜索,它比仅仅迭代更快

如果有很多行,也可以从使用ConcurrentHashMap和同步列表开始。这可以显著减少争用,这可能足以解决性能问题,而且很简单

当你提到你“在所说的大地图上反复挑选匹配的键”时,我想知道你是否使用了最好的数据结构。有没有一种方法可以避免这种迭代


注意,Guava包括多个具有不同性能特征的multimap实现。正如Zwei提到的,不可变多重映射比可变多重映射具有更好的性能。如果代码检查多重映射是否包含特定值,则SetMultimaps会更快;否则,ArrayListMultimap的性能会更好。

我有一个要求,我必须有一个
映射,其中映射上的插入是并发的,并且也在相应的集合上,但是一旦从映射中使用了一个键,就必须将其删除,试想一下,如果一个作业每两秒钟运行一次,从一个特定的键消耗整个
集,但插入是完全并发的,以便在作业开始时缓冲大多数值,那么下面是我的实现:

注意:我使用Guava的helper类映射来创建并发映射,而且,这个解决方案模拟了Java并发,在实践中如清单5.19所示:

import com.google.common.collect.MapMaker;

import java.util.concurrent.ConcurrentMap;

/**
 * Created by IntelliJ IDEA.
 * User: gmedina
 * Date: 18-Sep-2012
 * Time: 09:17:50
 */
public class LockMap<K extends Comparable>
{
  private final ConcurrentMap<K, Object> locks;

  public LockMap()
  {
    this(16, 64);
  }

  public LockMap(final int concurrencyLevel)
  {
    this(concurrencyLevel, 64);
  }

  public LockMap(final int concurrencyLevel, final int initialCapacity)
  {
    locks=new MapMaker().concurrencyLevel(concurrencyLevel).initialCapacity(initialCapacity).weakValues().makeMap();
  }

  public Object getLock(final K key)
  {
    final Object object=new Object();
    Object lock=locks.putIfAbsent(key, object);
    return lock == null ? object : lock;
  }

}


import com.google.common.collect.MapMaker;
import com.google.common.collect.Sets;

import java.util.Collection;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;

/**
 * A general purpose Multimap implementation for delayed processing and concurrent insertion/deletes.
 *
 * @param <K> A comparable Key
 * @param <V> A comparable Value
 */
public class ConcurrentMultiMap<K extends Comparable, V extends Comparable>
{
  private final int initialCapacity;
  private final LockMap<K> locks;
  private final ConcurrentMap<K, Set<V>> cache;

  public ConcurrentMultiMap()
  {
    this(16, 64);
  }

  public ConcurrentMultiMap(final int concurrencyLevel)
  {
    this(concurrencyLevel, 64);
  }

  public ConcurrentMultiMap(final int concurrencyLevel, final int initialCapacity)
  {
    this.initialCapacity=initialCapacity;
    cache=new MapMaker().concurrencyLevel(concurrencyLevel).initialCapacity(initialCapacity).makeMap();
    locks=new LockMap<K>(concurrencyLevel, initialCapacity);
  }

  public void put(final K key, final V value)
  {
    synchronized(locks.getLock(key)){
      Set<V> set=cache.get(key);
      if(set == null){
        set=Sets.newHashSetWithExpectedSize(initialCapacity);
        cache.put(key, set);
      }
      set.add(value);
    }
  }

  public void putAll(final K key, final Collection<V> values)
  {
    synchronized(locks.getLock(key)){
      Set<V> set=cache.get(key);
      if(set == null){
        set=Sets.newHashSetWithExpectedSize(initialCapacity);
        cache.put(key, set);
      }
      set.addAll(values);
    }
  }

  public Set<V> remove(final K key)
  {
    synchronized(locks.getLock(key)){
      return cache.remove(key);
    }
  }

  public Set<K> getKeySet()
  {
    return cache.keySet();
  }

  public int size()
  {
    return cache.size();
  }

}
import com.google.common.collect.MapMaker;
导入java.util.concurrent.ConcurrentMap;
/**
*由IntelliJ IDEA创建。
*用户:gmedina
*日期:2012年9月18日
*时间:09:17:50
*/
公共类锁图
{
私有最终ConcurrentMap锁;
公共锁图()
{
这(16,64);
}
公共锁图(最终int并发级别)
{
这(第64级);
}
公共锁图(最终int并发级别、最终int初始容量)
{
locks=new MapMaker().concurrencyLevel(concurrencyLevel).initialCapacity(initialCapacity).WeakValue().makeMap();
}
公共对象getLock(最终K密钥)
{
最终对象=新对象();
Object lock=locks.putIfAbsent(键,对象);
返回lock==null?对象:lock;
}
}
导入com.google.common.collect.MapMaker;
导入com.google.common.collect.set;
导入java.util.Collection;
导入java.util.Set;
导入java.util.concurrent.ConcurrentMap;
/**
*用于延迟处理和并发插入/删除的通用多映射实现。
*
*@param一个可比较的键
*@param A可比值
*/
公共类ConcurrentMultiMap
{
私人最终能力;
私有最终锁图锁;
私有最终ConcurrentMap缓存;
公共ConcurrentMultiMap()
{
这(16,64);
}
公共ConcurrentMultiMap(最终int ConcurrentLevel)
{
这(第64级);
}
公共ConcurrentMultiMap(最终整数并发级别,最终整数初始容量)
{
这个.initialCapacity=initialCapacity;
cache=new MapMaker().concurrencyLevel(concurrencyLevel).initialCapacity(initialCapacity).makeMap();
锁=新锁映射(并发级别,初始容量);
}
公开作废认沽权(最终K键,最终V值)
{
已同步(锁。getLock(键)){
Set=cache.get(key);
if(set==null){
set=Sets.newHashSetWithExpectedSize(初始容量);
cache.put(key,set);
}
增加(价值);
}
}
公共void putAll(最终K键、最终集合值)
{
已同步(锁。getLock(键)){
Set=cache.get(key);
if(set==null){
set=Sets.newHashSetWithExpectedSize(初始容量);
cache.put(key,set);
}
set.addAll(值);
}
}
公共集删除(最终K键)
{
已同步(锁。getLock(键
private Multimap<Phase, ResultingState> phaseResults = HashMultimap.create();

/**
 * @param withState is the state to be verified.
 * @param onPhase is the phase to be verified.
 * @return Whether the given result was reported in the given phase.
 */
public boolean wasReported(ResultingState withState, Phase onPhase) {
    return phaseResults.containsKey(onPhase) && phaseResults.get(onPhase).contains(withState);
}

/**
 * @param resultingState is the resulting state.
 * @return Whether the given resulting state has ever been reported.
 */
public boolean anyReported(ResultingState resultingState) {
    return phaseResults.values().contains(resultingState);
}