2013-03-25 16 views
11

Jestem nowym użytkownikiem języka Java i ćwiczę, tworząc uproszczony klasyfikator NaiveBayes. Nadal jestem nowicjuszem do zgłaszania obiektów i zastanawiam się, co zrobić, aby zainicjować HashMap z HashMaps. Podczas wstawiania nowych obserwacji do klasyfikatora, mogę utworzyć nową HashMap dla niewidocznej nazwy obiektu w danej klasie, ale czy muszę zainicjować?Java - Inicjowanie mapy HashMap HashMaps

Uwaga: to pytanie nie jest specyficzne dla klasyfikatorów Naive Bayes, tylko dlatego, że podam jakiś kontekst.

+1

"_... czy muszę zainicjować? _" ** Tak **. – jlordo

+3

A HashMap z HashMaps to zwykle znak, że brakuje obiektów i enkapsulacji. –

+0

Fajnie, mogę to docenić. Czy masz jakieś rady? Sposób w jaki o tym myślałem to posiadanie dwupoziomowego hasha, więc na przykład, gdyby to było wykrywanie spamu, mógłbym mieć "{spam: {" konto bankowe ": 3," viagra ": 9}' Jakie są twoje myśli ? –

Odpowiedz

18

Tak, musisz go zainicjować.

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

Gdy chcesz dodać wartość do class_feature_counts, trzeba instancję też:

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

Witam @BobTheBuilder, mam pytanie dotyczące tego, co zrobić po tym punkcie. Załóżmy, że w powyższym przykładzie miałem wtedy pobrać moją HashMap , która została zapisana w class_feature_counts pod klawiszem "MyKey". Zrobiłbym 'class_feature_count.get (" MyKey ")'. Zwraca jednak obiekt "Obiekt", a nie obiekt "HashMap". Jak rzutować ten obiekt Object na HashMap? Dzięki. –

+1

Czy możesz wpisać aktualny kod? – BobTheBuilder

+1

Witam @BobTheBuilder, proszę: https://pastebin.com/pJG49LMv –

2

Musisz musi utworzyć obiekt przed użyciem go za pomocą zmiennej referencyjnej. Nie ma znaczenia, jak skomplikowany jest ten obiekt. Nie jest wymagane inicjowanie go w konstruktorze, chociaż jest to najczęstszy przypadek. W zależności od potrzeb możesz zamiast tego użyć "leniwej inicjalizacji".

10

rekurencyjnych ogólnych struktur danych, takich jak mapy map, a nie wręcz zły pomysł, są często wskazujące na coś, co można naprawić - wewnętrzna mapa często może być obiektem pierwszego rzędu (który zawiera mapę), a nie tylko mapą. Nadal będziesz musiał zainicjować te wewnętrzne obiekty, ale często jest to znacznie czystszy i bardziej przejrzysty sposób rozwijania.

Na przykład, jeśli masz Map<A,Map<B,C>>, często przechowujesz mapę od A do Thing, ale sposób w jaki jest przechowywany Thing jest przypadkowo mapą. Będziesz często uważają, że jest czystsze i łatwiej się ukryć faktu, że rzecz jest mapa, a zamiast przechowywać mapowanie Map<A,Thing> gdzie rzeczą jest zdefiniowany jako:

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 
} 

Również spojrzeć Mulitmap/Multiset użyteczności guawy, w są bardzo użyteczne w takich przypadkach, w szczególności automatycznie inicjalizują wewnętrzne obiekty. Warto zwrócić uwagę na swój przypadek, praktycznie za każdym razem, gdy zaimplementujesz Map<E, Integer>, naprawdę chcesz Guise Multiset. Czystsze i bardziej przejrzyste.

+0

Dzięki za podpowiedź, przyjrzę się wielocianom Guawy. O rekurencyjnych ogólnych strukturach, co byś polecił? Wiem, że chcę mieć ustalony, dwupoziomowy skrót hashów, tak jak w powyższym komentarzu do wykrywania spamu. Czy poleciłbyś utworzyć coś podobnego do klasy featureCount, a następnie utworzyć jej HashMap? –

+1

Tak, to ogólny pomysł, zaktualizowałem moją odpowiedź. Guava pomaga rozwiązać mnóstwo typowych problemów z Javą, zdecydowanie sprawdź to. – dimo414

+1

Po prostu wyszukałem "java HashMap of HashMap" w nadziei na sugestię mniej niewygodnego projektu. Teraz, kiedy to widzę, jest to moment "duh", ale to jest idealne. Dziękuję Ci! – sfarbota

2
  1. Nie zadeklaruj swoich zmiennych z HashMap. To zbyt ograniczające.
  2. Tak, musisz zainicjować class_feature_counts. Będziesz dodawać do niego wpisy, więc musi to być poprawna mapa. W rzeczywistości, zainicjuj zarówno w deklaracji, a nie w konstruktorze, ponieważ istnieje tylko jeden sposób na każdy z nich. Mam nadzieję, że używasz Java 7 już teraz; w ten sposób jest to prostsze.

    prywatna mapa < Łańcuch, liczba całkowita> classCounts = new HashMap <>();

    prywatna mapa < Ciąg, mapa < Ciąg, liczba całkowita >> classFeatureCounts = new HashMap <>();

Kompilator wywnioskuje typy z <>. Zmieniłem również nazwy zmiennych na standardowy styl wielbłądy Java. Czy są podłączone classCounts i classFeatureCounts?

+0

W pewnym sensie tak, są ze sobą połączone, każdy z nich posiada informacje o liczbie wystąpień pewnych łańcuchów, na przykład, patrz rozdział 6 [Programowanie kolektywnej inteligencji] (http://shop.oreilly.com/product/9780596529321.do). Dzięki za informacje o obudowie wielbłąda. –