001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.util; 019 020import org.apache.yetus.audience.InterfaceAudience; 021import org.apache.yetus.audience.InterfaceStability; 022 023/** 024 * This is a very fast, non-cryptographic hash suitable for general hash-based lookup. See 025 * http://murmurhash.googlepages.com/ for more details. 026 * <p> 027 * The C version of MurmurHash 2.0 found at that site was ported to Java by Andrzej Bialecki (ab at 028 * getopt org). 029 * </p> 030 */ 031@InterfaceAudience.Private 032@InterfaceStability.Stable 033public class MurmurHash extends Hash { 034 private static MurmurHash _instance = new MurmurHash(); 035 036 public static Hash getInstance() { 037 return _instance; 038 } 039 040 @Override 041 public <T> int hash(HashKey<T> hashKey, int seed) { 042 int m = 0x5bd1e995; 043 int r = 24; 044 int length = hashKey.length(); 045 int h = seed ^ length; 046 047 int len_4 = length >> 2; 048 049 for (int i = 0; i < len_4; i++) { 050 int i_4 = (i << 2); 051 int k = hashKey.get(i_4 + 3); 052 k = k << 8; 053 k = k | (hashKey.get(i_4 + 2) & 0xff); 054 k = k << 8; 055 k = k | (hashKey.get(i_4 + 1) & 0xff); 056 k = k << 8; 057 // noinspection PointlessArithmeticExpression 058 k = k | (hashKey.get(i_4 + 0) & 0xff); 059 k *= m; 060 k ^= k >>> r; 061 k *= m; 062 h *= m; 063 h ^= k; 064 } 065 066 // avoid calculating modulo 067 int len_m = len_4 << 2; 068 int left = length - len_m; 069 int i_m = len_m; 070 071 if (left != 0) { 072 if (left >= 3) { 073 h ^= hashKey.get(i_m + 2) << 16; 074 } 075 if (left >= 2) { 076 h ^= hashKey.get(i_m + 1) << 8; 077 } 078 if (left >= 1) { 079 h ^= hashKey.get(i_m); 080 } 081 082 h *= m; 083 } 084 085 h ^= h >>> 13; 086 h *= m; 087 h ^= h >>> 15; 088 089 return h; 090 } 091}