创建一个映射/缓存,它将使用默认构造函数为新键生成的对象

时间:2012-10-26 21:24:00

标签: java map guava

我正在计算按属性分组的统计信息。对于此属性的每个类别(以String s给出),我得到了我想要聚合的值。

为此,我需要一个从类别到DescriptiveStatistics的地图(由org.apache.commons.math.stat.descriptive提供)。在此地图中,我必须检查对于给定类别是否已创建相应的DescriptiveStatistics此检查以及新DescriptiveStatistics的创建应由地图完成。

我测试了Apache的LazyMap,但是非一般性导致我去了Guava的LoadingCache。这些方面的东西对我有用:

LoadingCache<String, DescriptiveStatistics> groupedStats =
        CacheBuilder.newBuilder()
        .build(new CacheLoader<String, DescriptiveStatistics>() {
            @Override
            public DescriptiveStatistics load(String key) {
                return new DescriptiveStatistics();
            }
        });

是否有一个“罗嗦”的解决方案?一个不需要我为了实例化对象而抛出一个匿名类?

3 个答案:

答案 0 :(得分:4)

您的原始代码正是Guava团队希望您编写的代码。

我们倾向于避免反思(当然,除了com.google.common.reflect)。它往往是脆弱的,并且失去了编译时检查的好处 - 如果一个特定的类没有拥有一个公共的无参数构造函数,而你使用clazz.newInstance(),你就不会' t发现直到运行时。编写直接实现可能会花费你一两行,但我们认为它的好处是值得的。

答案 1 :(得分:0)

我想要更少的罗嗦解决方案创建一个用于缓存的类。

因为有人设计API并不总是让每个人都开心。番石榴缓存非常灵活且适应性强。另外几行代码应该不是问题。

答案 2 :(得分:0)

这是我在减少用户代码中的冗余的想法:一个类Creator<T>,它正如它所说的那样。

LoadingCache<String, SummaryStatistics> groupedStats =
    CacheBuilder.newBuilder().build(
        CacheLoader.from(Creators.of(SummaryStatistics.class)));

我想知道这样的野兽是否存在;我在实现Supplier<T>的类中找不到它。这是一个可能的实现,所有类都在同一个包中:

import com.google.common.base.Supplier;

public class Creator<T> implements Supplier<T> {

    private Class<T> class1;

    Creator(Class<T> class1) {
        this.class1 = class1;
    }

    @Override
    public T get() {
        try {
            return class1.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(
                    "Cannot instantiate object of type "
                        + class1.getCanonicalName(),
                    e);
        }
    }

}

public class Creators {
    public static <T> Creator<T> of(Class<T> class1) {
        return new Creator<T>(class1);
    }
}

当然,这可以推广到使用带参数的构造函数。