Java - 初始化哈希映射的哈希映射

2022-09-02 19:56:06

我是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
     }
}

请注意,这个问题不是特定于朴素贝叶斯分类器的,只是以为我会提供一些上下文。


答案 1

是的,您需要初始化它。

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);

答案 2

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

例如,如果你有一个,你经常真正存储A到Thing的地图,但Thing的存储方式恰好是一个地图。您经常会发现隐藏 Thing 是地图的事实,而是存储 thing 定义位置的映射,这样会更清晰、更容易:Map<A,Map<B,C>>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>