Java - Инициализировать хэш-карту HashMaps
Я новичок в java и занимаюсь созданием упрощенного классификатора NaiveBayes. Я еще новичок в создании экземпляра объекта и задаюсь вопросом, что делать, чтобы инициализировать HashMap из HashMaps. При вставке новых наблюдений в классификатор я могу создать новый 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, просто подумал, что я предоставил бы какой-то контекст.
Ответы
Ответ 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
Рекурсивные общие структуры данных, такие как карты карт, а не прямая плохая идея, часто указывают на то, что вы могли бы реорганизовать, - внутренняя карта часто может быть объектом первого порядка (который содержит карту), а не просто карта. Вам все равно придется инициализировать эти внутренние объекты, но часто это намного более чистый и понятный способ разработки.
Например, если у вас есть Map<A,Map<B,C>>
, вы часто действительно сохраняете карту A to 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. Чище и понятнее.
Ответ 3
Вы должны создать объект перед его использованием через ссылочную переменную. Неважно, насколько сложным является этот объект. Вы не обязаны инициализировать его в конструкторе, хотя это наиболее распространенный случай. В зависимости от ваших потребностей вы можете использовать вместо этого "ленивую инициализацию".
Ответ 4
- Не указывайте свои переменные с помощью
HashMap
. Это слишком ограничивает.
-
Да, вам нужно инициализировать class_feature_counts
. Вы будете добавлять в него записи, поэтому это должна быть действительная карта. Фактически, инициализируйте как при объявлении, так и не в конструкторе, так как для каждого из них есть только один способ. Я надеюсь, что вы используете Java 7; это проще.
private Map < String, Integer > classCounts = new HashMap < > ();
private Map < String, Map < String, Integer → classFeatureCounts = new HashMap < > ();
Компилятор выведет типы из < > . Кроме того, я изменил имена переменных на стандартный стиль Java-верблюда. Связаны ли classCounts
и classFeatureCounts
?