1

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>

ただし、キャッシュへの一時的な参照を使用してマップを作成すると、正常に機能します。

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

なぜこれが機能し、最初のサンプルが機能しないのですか?

4

2 に答える 2

10

これは Java のジェネリックの誤りです。この場合、ジェネリック型は推論できません。<K, V>新しく作成されたキャッシュをCache<K, V>ではなくとして扱うよう Java に指示するために追加する必要があり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);

Angelika Langer のJava Generics FAQのこの部分を参照してください。

于 2013-02-06T13:32:01.337 に答える
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();
  }
}
于 2015-03-13T16:03:41.643 に答える