Java generics - Map of (typed) maps

标签 java generics caching map

我正在研究一种(简单的)缓存解决方案,其中服务可以从缓存映射中请求缓存对象。 Cache 对象本质上也像 Map 一样工作,具有键和值以及访问和存储对象的方法。

我提出了以下解决方案,但如您所见,它包含一个转换(因为 get() 无法知道嵌套对象的类型应该是什么)。

private final  Map<String, Cache<?, ?>> caches = new HashMap<String, Cache<?, ?>>();

public <K, V> Cache<K, V> getOrCreateCache(String identifier) {
    if (caches.containsKey(identifier)) {
        return (Cache<K, V>) caches.get(identifier);
    } else {
        Cache<K, V> cache = new CacheImpl<K, V>();
        caches.put(identifier, cache);
        return cache;
    }
}

private void test() {
    Cache<String, String> strCache = getOrCreateCache("string cache");
    strCache.set("key", "value");
}

现在,我的问题:

  • 只要正确处理类转换异常,这是一种“安全”的方法吗? (可能会捕获那些并将它们打包到自定义异常类中)
  • 是否有“安全”的替代方案?一个使用泛型,如果可能的话,因为我喜欢它们而不喜欢转换。
  • (没有直接关系)这是线程安全的吗?我假设不是,但是,我不是线程专家。仅使整个方法同步就足够了吗,或者(有六个客户端)会导致过多的开销/锁定吗?对此有一个巧妙的解决方案吗?

编辑:哇,很多答案,谢谢!在这里编辑以描述我在实际测试时发现的一个奇怪之处:<​​/p>

    Cache<String, String> someCache = service.getOrCreateCache(cacheIdentifier);
    someCache.set("asdf", "sdfa");
    Cache<String, Integer> someCacheRetrievedAgain = service.getOrCreateCache(cacheIdentifier);
    System.out.println(someCacheRetrievedAgain.get("asdf")); // prints "sdfa". No errors whatsoever. Odd.

最佳答案

您可以创建一个复合键,它包含您当前的标识符和两个类实例(一个用于键,一个用于值)

public <K, V> Cache<K, V> getOrCreateCache(String identifier, Class<K> keyClass, Class<V> valueClass) {
  Identifier cacheIdentifier = new Identifier(identifier, keyClass, valueClass);
  // safe cast as we know that this cacheIdentifier must has a Cache<K, V>
  Cache<K, V> cache = (Cache<K, V>) caches.get(identifier);
  if (cache == null) {
    cache = new CacheImpl<K, V>();
    caches.put(cacheIdentifier, cache);
  }
  return cache;
}

/*
 * not the most efficient implementation, but correctly implements hashCode and equals
 * which is all we need
 */
private static class CacheIdentifier extends ArrayList<Object> {
  private CacheIdentifier(String identifier, Class<K> keyClass, Class<V> valueClass) {
    super(3);
    // TODO check for null
    add(identifier);
    add(keyClass);
    add(valueClass);
  }
}

为了使这个线程安全,使用 ConcurrentHashMap而不是连同 putIfAbsent(..)

关于Java generics - Map of (typed) maps,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4733273/

相关文章:

java - 缓存一致性在无限循环演示中不起作用

java - 从字符串中提取多个 TimeUnit

java - 'A4J' 未定义

java - 扫描仪类帮助

通过 Comparator<T> 进行的 Java 排序将大部分时间花在 compare(Object,Object) 上

go - 约束满足 3 个约束数组。使用方法 float

c# - C# 泛型问题,如何通过 Func 传递输入和输出

c# - ConfigurationChangeWatcher.Poller()

java - 传递泛型类型的问题

asp.net - 缓存策略、css/js/images 如何让它们在我每次完全回发时不加载?