Java - 初始化HashMaps的HashMap

时间:2013-03-25 22:48:11

标签: java oop initialization

我是java的新手,通过创建一个简单的NaiveBayes分类器来练习。我仍然是对象实例化的新手,并想知道如何初始化HashMaps的HashMap。在将新观察值插入分类器时,我可以为给定类中看不见的特征名创建一个新的HashMap,但是我是否需要初始化?

import java.util.HashMap;

public class NaiveBayes {

    private HashMap<String, Integer> class_counts;
    private HashMap<String, HashMap<String, Integer>> class_feature_counts;

    public NaiveBayes() {
        class_counts = new HashMap<String, Integer>();
        // do I need to initialize class_feature_counts?
    }

    public void insert() {
        // todo
        // I think I can create new hashmaps on the fly here for class_feature_counts
    }

    public String classify() {
        // stub 
        return "";
    }

    // Naive Scoring:
    // p( c | f_1, ... f_n) =~ p(c) * p(f_1|c) ... * p(f_n|c)
    private double get_score(String category, HashMap features) {
       // stub
       return 0.0;
    }

    public static void main(String[] args) {
        NaiveBayes bayes = new NaiveBayes();
       // todo
     }
}

请注意,这个问题并不是针对Naive Bayes分类器的,因为我想提供一些上下文。

4 个答案:

答案 0 :(得分:20)

是的,你需要初始化它。

class_feature_counts = new HashMap<String, HashMap<String, Integer>>();

如果要为class_feature_counts添加值,还需要实例化它:

HashMap<String, Integer> val = new HashMap<String, Integer>();
// Do what you want to do with val
class_feature_counts.put("myKey", val);

答案 1 :(得分:11)

递归通用数据结构,如地图地图,虽然不是一个彻头彻尾的坏主意,但往往表明你可以重构的东西 - 内部地图通常可能是一阶对象(它拥有一张地图),而不仅仅是一个地图。你仍然需要初始化这些内部对象,但它通常是一种更清洁,更清晰的开发方式。

例如,如果您有一个Map<A,Map<B,C>>,那么您经常会将A的地图存储到Thing中,但Thing的存储方式恰好是一张地图。你经常会发现它更清晰,更容易隐藏Thing是一个地图的事实,而是存储Map<A,Thing>的映射,其中的东西被定义为:

public class Thing {
    // Map is guaranteed to be initialized if a Thing exists
    private Map<B,C> data = new Map<B,C>();

    // operations on data, like get and put
    // now can have sanity checks you couldn't enforce when the map was public
}

另外,查看Guava的Mulitmap/Multiset实用程序,它们对于这样的情况非常有用,特别是它们会自动执行内部对象初始化。对于你的情况,几乎在任何时候你实现Map<E, Integer>你真的想要一个Guava Multiset。更清洁,更清晰。

答案 2 :(得分:2)

必须创建对象,然后才能通过引用变量使用它。这个对象有多复杂并不重要。您不需要在构造函数中初始化它,尽管这是最常见的情况。根据您的需要,您可能希望使用“延迟初始化”。

答案 3 :(得分:2)

  1. 请勿使用HashMap声明您的变量。这太有限了。
  2. 是的,您需要初始化class_feature_counts。您将添加条目,因此它必须是有效的地图。实际上,在声明而不是构造函数中初始化它们,因为每个启动只有一种方法。我希望你现在正在使用Java 7;这种方式更简单。

    私人地图&lt;字符串,整数&gt; classCounts = new HashMap&lt;&gt;();

    私人地图&lt;字符串,地图&lt;字符串,整数&gt;&gt; classFeatureCounts = new HashMap&lt;&gt;();

  3. 编译器将从&lt;&gt;中推断出类型。此外,我将变量名称更改为标准Java驼峰式样式。 classCountsclassFeatureCounts是否已关联?