使用基于Guava中缓存的映射键入错误

时间:2013-02-06 13:23:28

标签: java generics guava

我正在尝试使用Guava来模拟LRU地图。

Map<K, V> map = CacheBuilder.newBuilder()
        .maximumSize(maxSize)
        .build() // not using a cache loader
        .asMap();

但是当我尝试这样做时,我得到一个错误。

Type mismatch: cannot convert from ConcurrentMap<Object,Object> to Map<K,V>

但是,如果我使用对缓存的临时引用创建Map,它可以正常工作。

Cache<K, V> cache = CacheBuilder.newBuilder()
        .maximumSize(maxSize)
        .build();
Map<K, V> map = cache.asMap();

为什么这样做而第一个样本没有?

2 个答案:

答案 0 :(得分:8)

这是Java的泛型错误 - 在这种情况下无法推断泛型类型。您应该添加<K, V>告诉Java将新创建的缓存视为Cache<K, V>,而不是Cache<Object, Object>

private static <K, V> Map<K, V> makeMap(final int maxSize) {
  return CacheBuilder.newBuilder()
      .maximumSize(maxSize)
      .<K, V>build() // not using a cache loader
      .asMap();
}

然后它会起作用:

final Map<Long, String> map = makeMap(10);

请参阅this part of Angelika Langer's Java Generics FAQs

答案 1 :(得分:1)

这是我从Xaerxess的回答中得出的,用法:

private final Map<String, List<Condition>> waitersByKey=MapUtil.create(5, 1000);

MapUtil.java:

import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalListener;

public class MapUtil {

  /**
   * Value for items which are unrestricted (-1)
   */
  public static final int UNRESTRICTED=-1;

  /**
   * Create a generic map that will not exceed max size
   * @param maxSize
   * @return created map
   */
  public static <K,V> Map<K,V> createWithMaxSize(int maxSize) {
    return create(UNRESTRICTED,maxSize);
  }

  /**
   * Create a generic map that will expire objects if not accessed within a given number of minutes
   * @param expireInMins
   * @return created map
   */
  public static <K,V> Map<K,V> createWithExpiration(int expireInMins) {
    return create(expireInMins,UNRESTRICTED,UNRESTRICTED);
  }

  /**
   * Creates a map with an initial size.  Reduces growth performance hit.
   * @param initialSize
   * @return created map
   */
  public static <K,V> Map<K,V> createWithInitialSize(int initialSize) {
    return create(UNRESTRICTED,UNRESTRICTED,initialSize);
  }

  /**
   * Create generic map that expires values with max size
   * @param expireInMins max age of unaccessed items in minutes, or UNRESTRICTED
   * @param maxSize max number of items before oldest is removed, or UNRESTRICTED
   * @return created map
   */
  public static <K,V> Map<K,V> create(int expireInMins, int maxSize) {
    return create(expireInMins,maxSize,UNRESTRICTED);
  }

  /**
   * Create generic map that expires values with max size
   * @param expireInMins max age of unaccessed items in minutes, or UNRESTRICTED
   * @param maxSize max number of items before oldest is removed, or UNRESTRICTED
   * @param removalListener listener called on item removal, if not null
   * @return created map
   */
  public static <K,V> Map<K,V> create(int expireInMins, int maxSize, RemovalListener<K, V> removalListener) {
    return create(expireInMins,maxSize,UNRESTRICTED, removalListener);
  }

  /**
   * Convenience method to build a Guava cache as generic map.
   * http://stackoverflow.com/a/14730359/303442
   * @param expireInMins max age of unaccessed items in minutes, or UNRESTRICTED
   * @param maxSize max number of items before oldest is removed, or UNRESTRICTED
   * @param initialCapacity initial size in elements, reduces growth performance hit. UNRESTRICTED for default
   * @return created map
   */
  public static <K,V> Map<K,V> create(int expireInMins, int maxSize, int initialCapacity) {
    return create(expireInMins,maxSize,initialCapacity,null);
  }

  /**
   * Convenience method to build a Guava cache as generic map.
   * http://stackoverflow.com/a/14730359/303442
   * @param expireInMins max age of unaccessed items in minutes, or UNRESTRICTED
   * @param maxSize max number of items before oldest is removed, or UNRESTRICTED
   * @param initialCapacity initial size in elements, reduces growth performance hit. UNRESTRICTED for default
   * @param removalListener listener called on item removal, if not null
   * @return created map
   */
  public static <K,V> Map<K,V> create(int expireInMins, int maxSize, int initialCapacity,RemovalListener<K, V> removalListener) {
    CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
    if (expireInMins>-1)
      builder.expireAfterWrite(expireInMins, TimeUnit.MINUTES);
    if (maxSize>-1)
      builder.maximumSize(1000);
    if (initialCapacity>-1)
      builder.initialCapacity(initialCapacity);
    if (removalListener!=null)
      builder.removalListener(removalListener);
    return builder.<K,V>build().asMap();
  }
}