1 回答
TA贡献1836条经验 获得超3个赞
您可以创建一个自定义类,包装LoadingCache<Key<?>, Object>如下:
class HeterogeneousCache {
private final LoadingCache<Key<?>, Object> cache;
public <T> T get(Key<T> key) throws ExecutionException {
return key.getType().cast(cache.get(key));
}
}
@Value // provides constructor, getters, equals, hashCode
class Key<T> {
private final String identifier;
private final Class<T> type;
}
(为了简单起见,我使用了 Lombok 的@Value注释)
当然,这只是一个存根,您可能需要根据自己的需要进行调整。主要问题可能是您无法获得Class<List<ObjectABC>>- 您只能获得Class<List>. 最简单的方法是将 包装List<ObjectABC>在一些自定义类型中。更难的方法(不推荐)是使用 Guava 的TypeToken.
归因:此答案基于Frank Appel题为How to Map Distinct Value Types Using Java Generics的帖子,该帖子本身基于来自Effective Java 的Joshua Bloch的类型安全异构容器。
编辑:一个完整的解决方案
由于 OP 想要List<T>结果,并且因为他需要 的实例TypeReference<T>,我Class<T>用TypeReference<T>in替换Key<T>:
@Value // provides constructor, getters, equals, hashCode
class Key<T> {
private final String identifier;
private final TypeReference<T> typeReference;
}
这是CustomHeterogeneousCache现在的样子:
class CustomHeterogeneousCache {
private final LoadingCache<Key<?>, List<?>> cache = CacheBuilder.newBuilder()
.expireAfterAccess(10, TimeUnit.MINUTES)
.maximumSize(25)
.build(CacheLoader.from(this::computeEntry));
@SuppressWarnings("unchecked")
public <T> List<T> getEntry(Key<T> key) {
return (List<T>) cache.getUnchecked(key);
}
private <T> List<T> computeEntry(Key<T> key) {
final JoiObjectMapper mapper = new JoiObjectMapper();
final Collection<File> allConfigFiles = FileUtils.listFiles(new File(key.getIdentifier()), null, true);
return allConfigFiles.stream()
.map(configFile -> {
try {
return mapper.readValue(configFile, key.getTypeReference());
} catch (Exception e) {
throw new RuntimeException(e);
}
})
.collect(Collectors.toList());
}
}
由于 的实现TypeReference没有值语义,用户必须确保每个都Key被创建一次,然后只被引用,例如:
class Keys {
public static final Key<ObjectABC> ABC = new Key<>("/root/Desktop/folder1", new TypeReference<ObjectABC>() {
});
public static final Key<ObjectDEF> DEF = new Key<>("/root/Desktop/folder2", new TypeReference<ObjectDEF>() {
});
}
添加回答
举报