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 k = hashKey.getIntLE(i << 2); 051 k *= m; 052 k ^= k >>> r; 053 k *= m; 054 h *= m; 055 h ^= k; 056 } 057 058 // avoid calculating modulo 059 int len_m = len_4 << 2; 060 int left = length - len_m; 061 int i_m = len_m; 062 063 if (left != 0) { 064 if (left >= 3) { 065 h ^= hashKey.get(i_m + 2) << 16; 066 } 067 if (left >= 2) { 068 h ^= hashKey.get(i_m + 1) << 8; 069 } 070 if (left >= 1) { 071 h ^= hashKey.get(i_m); 072 } 073 074 h *= m; 075 } 076 077 h ^= h >>> 13; 078 h *= m; 079 h ^= h >>> 15; 080 081 return h; 082 } 083}