Page List

Search on the blog

2013年9月15日日曜日

OSS日記(2) HashMapで最頻値を計算するときはIntegerよりMutableIntの方がいい

org.apache.commons.lang3.ObjectUtils#modeのソースを読んでいたら、MutableIntという見慣れないクラスが使われていた。このクラスもCommons Langが提供しているものらしい。
int型のラッパークラスIntegerはimmutableなので、副作用を伴う使い方をしたい場合はMutableIntを使った方がいいということだろうか。確かにそっちの方が速そうだ。

ということで実験してみた。

ソースコード
あるデータ集合内に現れるデータの頻度を数えるような簡単なサンプルを書いて比較。 まず普通のIntegerを使った場合。
package com.kenjih.test;

import java.util.HashMap;
import java.util.Map;

public class Clazz {
    public void run() {
        final String[] names = { "Alice", "Bob", "Carol", "Dave" };

        Map<String, Integer> frequence = new HashMap<String, Integer>();
        for (int i = 0; i < 100000000; i++) {
            String name = names[i % 4];
            if (!frequence.containsKey(name))
                frequence.put(name, 0);
            int cnt = frequence.get(name);
            frequence.put(name, ++cnt);
        }

        System.out.println(frequence);
    }

    public static void main(String[] args) {
        new Clazz().run();
    }
}

次にMutableIntを使った場合。
package com.kenjih.test;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.mutable.MutableInt;

public class Clazz {
    public void run() {
        final String[] names = { "Alice", "Bob", "Carol", "Dave" };

        Map<String, MutableInt> frequence = new HashMap<String, MutableInt>();
        for (int i = 0; i < 100000000; i++) {
            String name = names[i % 4];
            if (!frequence.containsKey(name))
                frequence.put(name, new MutableInt());
            frequence.get(name).increment();
        }

        System.out.println(frequence);
    }

    public static void main(String[] args) {
        new Clazz().run();
    }
}

比較結果
[比較環境]
CPU: Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz(4コア)
メモリ: 4GB

 [コンパイル/実行コマンド]
$ javac -cp ${HOME}/bin/commons-lang3-3.1/commons-lang3-3.1.jar -d bin src/com/kenjih/test/Clazz.java
$ time java -cp bin:${HOME}/bin/commons-lang3-3.1/commons-lang3-3.1.jar com.kenjih.test.Clazz

 [比較結果]
# valueの型がIntegerの場合
real 0m2.204s
user 0m2.156s
sys 0m0.100s

# valueの型がMutableIntの場合
real 0m1.339s
user 0m1.356s
sys 0m0.004s

0 件のコメント:

コメントを投稿