17

我是 java 新手,通过创建一个简单的 NaiveBayes 分类器来练习。我还是对象实例化的新手,想知道如何初始化 HashMap 的 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
     }
}

请注意,此问题并非特定于朴素贝叶斯分类器,只是想我会提供一些上下文。

4

4 回答 4

23

是的,你需要初始化它。

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);
于 2013-03-25T22:52:56.937 回答
14

递归通用数据结构,如地图的地图,虽然不是一个彻底的坏主意,但通常表明您可以重构一些东西- 内部地图通常可以是一阶对象(具有命名字段或内部地图),而不仅仅是一个地图。您仍然需要初始化这些内部对象,但它通常是一种更清洁、更清晰的开发方式。

例如,如果您有 a,Map<A,Map<B,C>>您通常会真正存储 A 到 Thing 的映射,但 Thing 的存储方式恰好是映射。您通常会发现隐藏 Thing 是一个地图这一事实更简洁、更容易,而是将 ThingMap<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。更干净更清晰。

于 2013-03-25T22:54:01.747 回答
2

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

于 2013-03-25T22:51:19.907 回答
2
  1. 不要用HashMap. 太局限了。
  2. 是的,您需要初始化class_feature_counts. 您将为其添加条目,因此它必须是有效的地图。事实上,在声明时初始化而不是在构造函数中初始化,因为每个启动方式只有一种。我希望你现在正在使用 Java 7;这种方式更简单。

    私有 Map<String, Integer> classCounts = new HashMap<>();

    私有 Map<String, Map<String, Integer>> classFeatureCounts = new HashMap<>();

编译器将从 <> 中推断出类型。此外,我将变量名更改为标准 Java 驼峰式风格。是否classCountsclassFeatureCounts连接?

于 2013-03-25T22:57:10.573 回答