如何实现Guava缓存来存储和获取不同类型的对象?

现在我的缓存如下所示:


public class TestCache {


    private LoadingCache<String, List<ObjectABC>> cache;


    TestCache() {

        cache = CacheBuilder.newBuilder().expireAfterAccess(10, TimeUnit.MINUTES).maximumSize(25)

                .build(new CacheLoader<String, List<ObjectABC>>(

                ) {

                    @Override

                    public List<ObjectABC> load(String key) throws Exception {

                        // TODO Auto-generated method stub

                        return addCache(key);

                    }


                });

    }


    private List<ObjectABC> addCache(String key) {

    final JoiObjectMapper mapper = new JoiObjectMapper();


        final Collection<File> allConfigFiles = FileUtils.listFiles(new File(key), null, true);

        final List<ObjectABC> configsList = new ArrayList<>();


        allConfigFiles.forEach(configFile -> {

            try {

                     configsList.add(mapper.readValue(configFile, new TypeReference<ObjectABC>() {

                      }));

            } catch (Exception e) {

                throw new RuntimeException(e);

            }

        });


        return configsList;

    }


    public List<ObjectABC> getEntry(String key) {

         try {

            return cache.get(key);

        } catch (ExecutionException e) {

            throw new NonRetriableException(String.format(

                    "Exception occured while trying to get data from cache for the key : {} Exception: {}",

                    key.toString(), e));

        }

    }

}

在上面的代码中,当我传递 a String key(它是本地文件夹的路径)时,它会获取该位置存在的所有文件并将它们映射到ObjectABC使用ObjectMapper.


现在我的问题是我想要一个通用的加载缓存,比如

LoadingCache<String, List<Object>>.


我想将不同文件夹中的文件映射到不同的对象,例如将/root/Desktop/folder1中的List<ObjectABC>文件映射到/root/Desktop/folder2 中的文件,List<ObjectDEF>并能够从缓存中存储和检索该信息。


如何将用于映射的对象的信息传递给缓存?


梵蒂冈之花
浏览 263回答 1
1回答

米脂

您可以创建一个自定义类,包装LoadingCache<Key<?>, Object>如下:class HeterogeneousCache {&nbsp; &nbsp; private final LoadingCache<Key<?>, Object> cache;&nbsp; &nbsp; public <T> T get(Key<T> key) throws ExecutionException {&nbsp; &nbsp; &nbsp; &nbsp; return key.getType().cast(cache.get(key));&nbsp; &nbsp; }}@Value // provides constructor, getters, equals, hashCodeclass Key<T> {&nbsp; &nbsp; private final String identifier;&nbsp; &nbsp; 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, hashCodeclass Key<T> {&nbsp; &nbsp; private final String identifier;&nbsp; &nbsp; private final TypeReference<T> typeReference;}这是CustomHeterogeneousCache现在的样子:class CustomHeterogeneousCache {&nbsp; &nbsp; private final LoadingCache<Key<?>, List<?>> cache = CacheBuilder.newBuilder()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .expireAfterAccess(10, TimeUnit.MINUTES)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .maximumSize(25)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .build(CacheLoader.from(this::computeEntry));&nbsp; &nbsp; @SuppressWarnings("unchecked")&nbsp; &nbsp; public <T> List<T> getEntry(Key<T> key) {&nbsp; &nbsp; &nbsp; &nbsp; return (List<T>) cache.getUnchecked(key);&nbsp; &nbsp; }&nbsp; &nbsp; private <T> List<T> computeEntry(Key<T> key) {&nbsp; &nbsp; &nbsp; &nbsp; final JoiObjectMapper mapper = new JoiObjectMapper();&nbsp; &nbsp; &nbsp; &nbsp; final Collection<File> allConfigFiles = FileUtils.listFiles(new File(key.getIdentifier()), null, true);&nbsp; &nbsp; &nbsp; &nbsp; return allConfigFiles.stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .map(configFile -> {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return mapper.readValue(configFile, key.getTypeReference());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (Exception e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new RuntimeException(e);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; })&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.toList());&nbsp; &nbsp; }}由于 的实现TypeReference没有值语义,用户必须确保每个都Key被创建一次,然后只被引用,例如:class Keys {&nbsp; &nbsp; public static final Key<ObjectABC> ABC = new Key<>("/root/Desktop/folder1", new TypeReference<ObjectABC>() {&nbsp; &nbsp; });&nbsp; &nbsp; public static final Key<ObjectDEF> DEF = new Key<>("/root/Desktop/folder2", new TypeReference<ObjectDEF>() {&nbsp; &nbsp; });}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java