001/* 002 * ModeShape (http://www.modeshape.org) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.modeshape.common.util; 017 018import java.util.Arrays; 019import org.modeshape.common.annotation.Immutable; 020 021/** 022 * Utilities for easily computing hash codes. The algorithm should generally produce good distributions for use in hash-based 023 * containers or collections, but as expected does always result in repeatable hash codes given the inputs. 024 */ 025@Immutable 026public class HashCode { 027 028 // Prime number used in improving distribution: 1,000,003 029 private static final int PRIME = 103; 030 031 /** 032 * Compute a combined hash code from the supplied objects. This method always returns 0 if no objects are supplied. 033 * 034 * @param objects the objects that should be used to compute the hash code 035 * @return the hash code 036 */ 037 public static int compute( Object... objects ) { 038 return _compute(0, objects); 039 } 040 041 /** 042 * Compute a combined hash code from the supplied objects using the supplied seed. 043 * 044 * @param seed a value upon which the hash code will be based; may be 0 045 * @param objects the objects that should be used to compute the hash code 046 * @return the hash code 047 */ 048 protected static int _compute( int seed, 049 Object... objects ) { 050 if (objects == null || objects.length == 0) { 051 return seed * HashCode.PRIME; 052 } 053 // Compute the hash code for all of the objects ... 054 int hc = seed; 055 for (Object object : objects) { 056 hc = HashCode.PRIME * hc; 057 if (object instanceof byte[]) { 058 hc += Arrays.hashCode((byte[])object); 059 } else if (object instanceof boolean[]) { 060 hc += Arrays.hashCode((boolean[])object); 061 } else if (object instanceof short[]) { 062 hc += Arrays.hashCode((short[])object); 063 } else if (object instanceof int[]) { 064 hc += Arrays.hashCode((int[])object); 065 } else if (object instanceof long[]) { 066 hc += Arrays.hashCode((long[])object); 067 } else if (object instanceof float[]) { 068 hc += Arrays.hashCode((float[])object); 069 } else if (object instanceof double[]) { 070 hc += Arrays.hashCode((double[])object); 071 } else if (object instanceof char[]) { 072 hc += Arrays.hashCode((char[])object); 073 } else if (object instanceof Object[]) { 074 hc += Arrays.hashCode((Object[])object); 075 } else if (object != null) { 076 hc += object.hashCode(); 077 } 078 } 079 return hc; 080 } 081 082 private HashCode() { 083 } 084 085}