P2Pとかプログラミング全般とか

P2Pアプリ開発を目指していこうかと。
基本、週末更新なので遅々として進まず。

MurmurHash を Java で書いてみた

2008-03-16 10:42:48 | Java
Matzにっきで取り上げられた MurmurHash を Java で書いてみた。
もともとのソースだと C の unsigned int でハッシュ値を計算していたので、Java では long で計算。
Java の int は signed だから桁を増やしたんだけど、
そのせいで 32 bit を超えた部分についてはマスクしてやる必要がでてしまった。
0xffffffffL でマスクするのはなんか不恰好だし遅いよなぁ…。
もうちょっとなんとかすべきかも。
一応、C で計算したのと同じハッシュ値が返る事は確認済み。

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;


public class MurmurHash {

    /**
     * @param args
     * @throws UnsupportedEncodingException
     */
    public static void main(String[] args) throws UnsupportedEncodingException {
        // TODO 自動生成されたメソッド・スタブ
        //byte[] b = { 1, 2, 3, };
        byte[] b = "de".getBytes("UTF-8");
        System.out.printf("%08xn", computeHash(b, 0));


    }

    public static long computeHash(byte[] b, long h)
    {
        final long m = 0x7fd652ad;
        final int r = 16;

        h += 0xdeadbeefL;

        ByteBuffer bb = ByteBuffer.wrap(b);
        bb.order(ByteOrder.LITTLE_ENDIAN);
        while (bb.remaining() >= 4) {
            h += 0xffffffffL & bb.getInt();

            h *= m;
            h &= 0xffffffffL;
            h ^= h >> r;
        }

        switch (bb.remaining())
        {
        case 3:
            h += (0xff & bb.get(bb.position() + 2)) << 16;
case 2: h += (0xff & bb.get(bb.position() + 1)) << 8;
case 1: h += (0xff & bb.get(bb.position())); h *= m; h &= 0xffffffffL; h ^= h >> r; } h *= m; h &= 0xffffffffL; h ^= h >> 10; h *= m; h &= 0xffffffffL; h ^= h >> 17; return h; } }