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