2013-03-25 3 views
11

저는 Java에 익숙하지 않고 단순한 NaiveBayes 분류자를 작성하여 연습합니다. 저는 여전히 객체 인스턴스화에 익숙하지 않고 HashMap의 HashMap을 초기화하기 위해해야 ​​할 일이 무엇인지 궁금합니다. 새로운 관측을 분류 자에 삽입 할 때 주어진 클래스에서 보이지 않는 피쳐 이름에 대해 새로운 HashMap을 만들 수 있지만 초기화해야합니까?Java - 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

"_... 초기화해야합니까? _"** 예 **. – jlordo

+3

그리고 HashMaps의 HashMap은 일반적으로 객체와 캡슐화가 없다는 표시입니다. –

+0

멋지다, 나는 그것을 알 수있다. 조언이 있니? 내가 생각하고있는 방식은 2 단계 해시를 갖는 것입니다. 예를 들어 이것이 스팸 탐지 일 경우'{spam : { "은행 계좌": 3, "viagra": 9}'당신의 생각은 무엇입니까? ? –

답변

18

예, 초기화해야합니다. 당신이 class_feature_counts에 값을 추가 할 때

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

, 당신은 너무 인스턴스화해야합니다

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

안녕하세요 @ BobTheBuilder,이 시점 이후에해야 할 일에 관한 질문이 있습니다. 위의 예제에서 classKey가 "MyKey"키 아래에있는 class_feature_counts에 저장된 HashMap 를 검색한다고 가정 해 보겠습니다. 나는'class_feature_count.get ("MyKey")'를 할 것이다. 그러나이 개체는 "HashMap"개체가 아니라 "Object"개체를 반환합니다. Object 객체를 HashMap으로 어떻게 캐스팅합니까? 감사. –

+1

실제 코드를 게시 할 수 있습니까? – BobTheBuilder

+1

안녕하세요 @BobTheBuilder, 여기 있어요 : https://pastebin.com/pJG49LMv –

2

은 참조 변수를 통해 개체를 사용하기 전에 개체를 만들어야합니다. 그 대상이 얼마나 복잡한 지 상관하지 않습니다. 가장 일반적인 경우이지만 생성자에서 초기화하지 않아도됩니다. 필요에 따라 "지연 초기화"를 대신 사용할 수 있습니다.

10

재귀 일반 데이터 구조,지도의지도처럼하지 명백한 나쁜 생각하면서, 자주 리팩터링 할 수있는 것을 나타내는 지표 - 내부지도는 단순히지도가 아닌 1 차 객체 (지도를 보유) 일 수 있습니다. 여전히 내부 객체를 초기화해야하지만, 개발하는 것이 훨씬 깔끔하고 명확한 방법입니다.

예를 들어 Map<A,Map<B,C>>이 있으면 실제로 A to 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 
} 

을, 구아바의 Mulitmap/Multiset 유틸리티에 보면, 이런 경우에는 매우 유용합니다. 특히 내부 객체 초기화를 자동으로 수행합니다. 귀하의 경우에 대해, 당신이 실제로 구현 한 언제든지 Map<E, Integer> Guava Multiset을 원합니다. 더 깨끗하고 깨끗합니다.

+0

팁 주셔서 감사합니다. 구아바의 멀티 세트를 살펴 보겠습니다. 재귀 일반 구조에 대해서는 무엇을 권하고 싶습니까? 위의 스팸 탐지 코멘트 에서처럼 해시의 고정 된 2 수준 해시를 갖고 싶습니다. featureCount 클래스와 같은 것을 생성하고 그 클래스의 HashMap을 생성하는 것이 좋습니다. –

+1

예, 그게 일반적인 아이디어입니다, 내 대답이 업데이트되었습니다. 구아바는 일반적인 자바 문제를 해결하는데 도움을줍니다. – dimo414

+1

Googled "HashMap의 Java HashMap"은 덜 어색한 디자인을 제안합니다. 이제 나는 이것을 보았습니다, 그것은 일종의 "앗"순간이었습니다. 그러나 이것은 완벽합니다. 고맙습니다! – sfarbota

2
  1. HashMap으로 변수를 선언하지 마십시오. 그것은 너무 제한적입니다.
  2. 예, class_feature_counts을 초기화해야합니다. 항목을 추가 할 것이므로 유효한지도 여야합니다. 사실, 각각을 시작할 수있는 방법이 하나뿐이기 때문에 생성자가 아니라 선언시에 초기화하십시오. 지금까지 Java 7을 사용하시기 바랍니다. 이 방법이 더 간단합니다.

    개인지도 < String, Integer> classCounts = new HashMap <>();

    개인지도 < 문자열,지도 < String, 정수 >> classFeatureCounts = new HashMap <>();

컴파일러는 <>에서 유형을 추론합니다. 또한 변수 이름을 표준 Java 낙타 사례 스타일로 변경했습니다. classCountsclassFeatureCounts이 (가) 연결되어 있습니까?

+0

어떤 의미에서는 예를 들어 연결되어 있고 특정 문자열의 발생 횟수에 대한 정보를 보유하고 있습니다. 예를 들어 [Programming Collective Intelligence] (http://shop.oreilly.com/product/9780596529321.do)의 6 장을 참조하십시오.). 카멜 케이스에 대해 머리를 주셔서 감사합니다. –