単語カウント用のハッシュクラスをつくる

やらなければいけないことがあるときほど,関係のないことをしたくなる.


bag-of-wordsをつくったり,ナイーブベイズを実装したり,ありとあらゆるところでめちゃくちゃハッシュを使う.そういう意味でJavaはきちっとしているけれど使いづらいなー,と思ってた.


Perlはハッシュの値がundefの場合,勝手に0と解釈してくれる.Rubyの場合はnilの場合のデフォルト値を設定できる.

my %word_count;
for(@word_list){
  $word_count{$_}++;
}


Javaの場合は,いちいちcontainsKey()で調べる必要があるし,更に値をインクリメントするためにいちいち一時変数に代入する必要がある.面倒くさいことこの上ない.

for(String word : wordList){
  if(wordHash.containsKey(word)){
    int tmp = wordHash.get(word); // ここはauto boxing機能でだいぶ楽になった
    tmp++;
    wordHash.put(word, tmp);

  }else{
    wordHash.put(word, 1);
  } 
}

こんな感じになる.(動作確認していない書き下しコードなのでバグあるかも)


こんなんだからJavaを使う気がうせていたのだが,不満があるならば自分用にカスタマイズすればいいじゃん,という考え方ができていなかった.

このブログのコメントを参考にいたしました.ありがとうございます.


というわけで,こんな感じのクラスを書いてみるテスト.クラスを作成するときにというようにgenericsの型パラメータを使うようにしていたら,「値のクラスがIntegerの場合」というような条件分岐ができなかった.(型パラメータのクラスを確認する方法が未だわからない,どうするんだろう?)


そもそもそんなことをやる必要がなくて,継承するクラスにHashMapというように型パラメータを与えてしまえばいい.

import java.util.HashMap;

public class WordHash extends HashMap<String, Integer>{

    /**
     * Adds hash counts
     * @param key Hash key
     * @param add_value Incremental value
     */
    public void addValue(String key, int add_value){
	if(this.containsKey(key)){
	    int tmp_value = this.get(key);
	    tmp_value += add_value;
	    this.put(key, tmp_value);
	}else{
	    this.put(key, add_value);
	}
    }
}