java - 根据键的类类型动态获取地图并避免“原始使用参数化类'Map'”
问题描述
我有一个缓存类,我在其中使用 2 HashMap
s 来保留缓存。
我希望能够选择正确的地图给定key
的类类型,以便:
- 如果
key
是 Long,则从 map 中获取值longKeyCache
- 如果
key
是字符串,则从 map 中获取值stringKeyCache
。
(假设用户只会传入 Long 或 String 键)
为此,我构建了 function getMapToUse
。
问题是我必须在没有任何类型限制的情况下将其返回类型清除为 Map。只有这样,函数才能正确编译,并且我能够使用返回的映射将缓存存储在后续代码 ( mapToUse.put(key, value)
) 中。
该代码有效,但我收到了来自 IDE 的警告 -Raw use of parameterized class 'Map'
有没有办法解决这个警告?提前致谢。
public class CacheManager {
private final Map<Long,String> longKeyCache = new WeakHashMap<>();
private final Map<String,Integer> stringKeyCache = new WeakHashMap<>();
public <K, V> V getCache(K key, Function<K, V> valueLoader) {
Map<K, V> mapToUse = getMapToUse(key);
return Optional.ofNullable(mapToUse.get(key))
// cache miss
.orElseGet(() -> {
V value = valueLoader.apply(key);
mapToUse.put(key, value);
return value;
});
}
// warning: Raw use of parameterized class 'Map'
private <K> Map getMapToUse(K key) {
if (key instanceof Long) {
return longKeyCache;
} else {
return stringKeyCache;
}
}
}
解决方案
如果您想保留这种设计(CacheManager
让“知道”两个具有不同类型的键和值的映射),那么您将不得不将映射转换为Map<K, V>
. 没有逃避这一点,因为编译器将无法猜测是哪种实际类型。
您将意识到泛型的目的之一是允许实现可以使用各种类型的相同功能,但同时应用类型安全检查。
该方法getCache( K, Function<K, V> )
正在返回V
,这意味着它V
可能是Integer
or String
。但是哪一个??编译器必须在方法被调用的地方归结为一个。
所以,这就是我将如何实现它:因为涉及到一组已知的小型映射键/值类型,所以泛型可能不是方法。相反,我会简单地使用重载方法。原因:调用者仍然有一个一致的 API,即编译时类型检查,这是泛型的主要目标。
public class CacheManager{
private final Map<Long,String> longKeyCache = new WeakHashMap<>();
private final Map<String,Integer> stringKeyCache = new WeakHashMap<>();
public String getCache( Long key, Function<Long, String> valueLoader) {
return Optional.ofNullable( longKeyCache.get(key) )
// cache miss
.orElseGet(() -> {
String value = valueLoader.apply(key);
longKeyCache.put(key, value);
return value;
});
}
public Integer getCache( String key, Function<String, Integer> valueLoader) {
return Optional.ofNullable( stringKeyCache.get(key) )
// cache miss
.orElseGet(() -> {
Integer value = valueLoader.apply(key);
stringKeyCache.put(key, value);
return value;
});
}
/* Testing code from here on. */
public static void main( String[] args ){
CacheManager cm = new CacheManager();
cm.addTestData();
System.out.println( cm.getCache( 200L, k -> k.toString() ) );
System.out.println( cm.getCache( "500S", k -> 800 ) );
System.out.println( cm.getCache( "900", k -> 900 ) );
}
private void addTestData() {
longKeyCache.put( 200L, "200S" );
longKeyCache.put( 201L, "201S" );
stringKeyCache.put( "500S", 500 );
stringKeyCache.put( "501S", 501 );
}
}
推荐阅读
- javascript - 我可以将 .map 数组转换为带双引号的逗号分隔数组吗?
- functional-programming - 如何在纯 FP 中强制执行“单一事实来源”?
- c# - JsonResult 在 ASP.NET CORE 2.1 中返回 Json
- api - Podio App Create 不尊重字段 external_id
- mirth - 如何使用 Mirth Connect 仅处理目录中的最新文件?
- jquery - 动态添加和删除标记 (L.MarkerCluster)
- javascript - 推送新块时无法获取块的先前哈希
- r - 具有多个变量的宽到长格式?
- javascript - 冻结数组的元素
- excel - 当我以编程方式删除工作表时,Excel 崩溃、修复和重新启动