All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.googlecode.ehcache.annotations.key.HashCodeCacheKeyGenerator Maven / Gradle / Ivy

There is a newer version: 1.2.0
Show newest version
/**
 * Copyright 2010 Nicholas Blair, Eric Dalquist
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.googlecode.ehcache.annotations.key;

import java.util.Arrays;
import java.util.Map;

/**
 * This key generator is a good option for fast but rough comparison of method invocations. The standard Java
 * hashCode method is used on the arguments to generate identity information. Essentially {@link Arrays#deepHashCode(Object[])}
 * is used except with a long instead of an int for a hash accumulator to provide a larger key space. This is
 * not a secure hashing algorithm.
 * 
 * 
 *  
 *      
 *      
 *  
 *  
 *      
 *      
 *  
 * 
ProsCons
* This is the fastest of the included key generation techniques by over 150% * * The generated hash code is only a long so the key is only 64bits long. It is possible for different * arguments to have the same hash code which would result in a key collision. *
* * @author Eric Dalquist * @version $Revision: 403 $ */ public class HashCodeCacheKeyGenerator extends AbstractCacheKeyGenerator { /** * Name of the bean this generator is registered under using the default constructor. */ public static final String DEFAULT_BEAN_NAME = "com.googlecode.ehcache.annotations.key.HashCodeCacheKeyGenerator.DEFAULT_BEAN_NAME"; protected static final long INITIAL_HASH = 1; protected static final long MULTIPLIER = 31; /** * @see AbstractCacheKeyGenerator#AbstractCacheKeyGenerator() */ public HashCodeCacheKeyGenerator() { } /** * @see AbstractCacheKeyGenerator#AbstractCacheKeyGenerator(boolean, boolean) */ public HashCodeCacheKeyGenerator(boolean includeMethod, boolean includeParameterTypes) { super(includeMethod, includeParameterTypes); } @Override public Long generateKey(Object... data) { return this.deepHashCode(data); } /** * @see Arrays#hashCode(long[]) */ protected final long hashCode(long a[]) { if (a == null) return 0; long result = INITIAL_HASH; for (final long element : a) { int elementHash = (int)(element ^ (element >>> 32)); result = MULTIPLIER * result + elementHash; } return result; } /** * @see Arrays#hashCode(int[]) */ protected final long hashCode(int a[]) { if (a == null) return 0; long result = INITIAL_HASH; for (final int element : a) result = MULTIPLIER * result + element; return result; } /** * @see Arrays#hashCode(short[]) */ protected final long hashCode(short a[]) { if (a == null) return 0; long result = INITIAL_HASH; for (final short element : a) result = MULTIPLIER * result + element; return result; } /** * @see Arrays#hashCode(char[]) */ protected final long hashCode(char a[]) { if (a == null) return 0; long result = INITIAL_HASH; for (final char element : a) result = MULTIPLIER * result + element; return result; } /** * @see Arrays#hashCode(byte[]) */ protected final long hashCode(byte a[]) { if (a == null) return 0; long result = INITIAL_HASH; for (final byte element : a) result = MULTIPLIER * result + element; return result; } /** * @see Arrays#hashCode(boolean[]) */ protected final long hashCode(boolean a[]) { if (a == null) return 0; long result = INITIAL_HASH; for (final boolean element : a) result = MULTIPLIER * result + (element ? 1231 : 1237); return result; } /** * @see Arrays#hashCode(float[]) */ protected final long hashCode(float a[]) { if (a == null) return 0; long result = INITIAL_HASH; for (final float element : a) result = MULTIPLIER * result + Float.floatToIntBits(element); return result; } /** * @see Arrays#hashCode(double[]) */ protected final long hashCode(double a[]) { if (a == null) return 0; long result = INITIAL_HASH; for (final double element : a) { long bits = Double.doubleToLongBits(element); result = MULTIPLIER * result + (int)(bits ^ (bits >>> 32)); } return result; } /** * @see Arrays#deepHashCode(Object[]) */ protected final long deepHashCode(Object a[]) { if (a == null) return 0; long result = INITIAL_HASH; for (final Object element : a) { final long elementHash = this.hashCode(element); result = MULTIPLIER * result + elementHash; } return result; } /** * @see Arrays#deepHashCode(Object[]) */ protected final long deepHashCode(Iterable a) { if (a == null) return 0; long result = INITIAL_HASH; for (final Object element : a) { final long elementHash = this.hashCode(element); result = MULTIPLIER * result + elementHash; } return result; } protected final long hashCode(Map.Entry e) { if (e == null) return 0; long result = INITIAL_HASH; final long keyHash = this.hashCode(e.getKey()); result = MULTIPLIER * result + keyHash; final long valueHash = this.hashCode(e.getValue()); result = MULTIPLIER * result + valueHash; return result; } protected final long hashCode(Object element) { if (element == null || !register(element)) { //Return 0 in place of the actual hash code in the case of null or a circular reference return 0; } try { long elementHash = 0; if (element instanceof Object[]) elementHash = deepHashCode((Object[]) element); else if (element instanceof byte[]) elementHash = hashCode((byte[]) element); else if (element instanceof short[]) elementHash = hashCode((short[]) element); else if (element instanceof int[]) elementHash = hashCode((int[]) element); else if (element instanceof long[]) elementHash = hashCode((long[]) element); else if (element instanceof char[]) elementHash = hashCode((char[]) element); else if (element instanceof float[]) elementHash = hashCode((float[]) element); else if (element instanceof double[]) elementHash = hashCode((double[]) element); else if (element instanceof boolean[]) elementHash = hashCode((boolean[]) element); else if (element instanceof Class) elementHash = getHashCode((Class)element); else if (element instanceof Double) elementHash = getHashCode((Double)element); else if (element instanceof Long) elementHash = getHashCode((Long)element); else if (element instanceof Enum) elementHash = getHashCode((Enum)element); else if (element instanceof Iterable) elementHash = deepHashCode((Iterable)element); else if (element instanceof Map) elementHash = deepHashCode(((Map)element).entrySet()); else if (element instanceof Map.Entry) elementHash = hashCode((Map.Entry)element); else elementHash = getHashCode(element); return elementHash; } finally { unregister(element); } } /** * Generate hash code for an Class which by default uses object identity hash codes */ protected long getHashCode(Class c) { return c.getName().hashCode(); } /** * Generate hash code for a Double, getting the more precise double as long bits value. */ protected long getHashCode(Double n) { return Double.doubleToLongBits(n); } /** * Generate hash code for a Long, getting the more precise long value. */ protected long getHashCode(Long n) { return n; } /** * Generate hash code for an Enum, uses a combination of the Class and name to generate a consistent hash code */ protected long getHashCode(Enum e) { return this.hashCode(new Object[] { e.getClass(), e.name() }); } /** * Generate hash code for an object */ protected long getHashCode(Object o) { return o.hashCode(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy