com.netflix.util.HashCode Maven / Gradle / Ivy
The newest version!
/*
*
* Copyright 2013 Netflix, Inc.
*
* 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.netflix.util;
/**
* Helper class for computing hash codes.
*
* The idea here is that objects that define "equals" to
* mean that a number of member variables are equal needs a
* hash code that is computed from those same member variables.
*
* Example:
*
* class MyClass {
* ...
* private int membVar1;
* private OtherClass membVar2;
* private float membVar3;
* ...
* // MyClass objects are equal iff they have the same content.
* public boolean equals(Object obj) {
* if (obj == this) {
* return true;
* } else if (obj == null || obj.getClass() != getClass()) {
* return false;
* }
* MyClass cObj = (MyClass)obj;
* return (membVar1 == cObj.membVar1)
* && HashCode.equalObjects(membVar2, cObj.membVar2)
* && (membVar3 == bVar3);
* }
*
* // The hash code needs to align with the
* // definition of equals.
* public int hashCode() {
* HashCode h = new HashCode();
* h.addValue(membVar1);
* h.addValue(membVar2);
* h.addValue(membVar2);
* return h.hashCode();
* }
* ...
* }
*
*/
public class HashCode {
/*
* Based on the algorithm in "Effective Java"
*/
// ========================================
// Static vars: public, protected, then private
// ========================================
private static final int SEED = 17;
private static final long SCALE = 37;
// ========================================
// Instance vars: public, protected, then private
// ========================================
private int mVal;
// ========================================
// Constructors
// ========================================
/**
* Create a new HashCode object
*/
public HashCode() {
mVal = SEED;
}
// ========================================
// Methods, grouped by functionality, *not* scope
// ========================================
/**
* Augment the current computed hash code with the
* value obj.
*
* @param obj value being added
* @return the new hash code.
*/
public int addValue(Object obj) {
return foldIn((obj != null) ? obj.hashCode() : 0);
}
/**
* Augment the current computed hash code with the
* value b.
*
* @param b value being added
* @return the new hash code.
*/
public int addValue(boolean b) {
return foldIn(b ? 0 : 1);
}
/**
* Augment the current computed hash code with the
* value i.
*
* @param i value being added
* @return the new hash code.
*/
public int addValue(byte i) {
return foldIn(i);
}
/**
* Augment the current computed hash code with the
* value i.
*
* @param i value being added
* @return the new hash code.
*/
public int addValue(char i) {
return foldIn(i);
}
/**
* Augment the current computed hash code with the
* value i.
*
* @param i value being added
* @return the new hash code.
*/
public int addValue(short i) {
return foldIn(i);
}
/**
* Augment the current computed hash code with the
* value i.
*
* @param i value being added
* @return the new hash code.
*/
public int addValue(int i) {
return foldIn(i);
}
/**
* Augment the current computed hash code with the
* value f.
*
* @param f value being added
* @return the new hash code.
*/
public int addValue(float f) {
return foldIn(Float.floatToIntBits(f));
}
/**
* Augment the current computed hash code with the
* value f.
*
* @param f value being added
* @return the new hash code.
*/
public int addValue(double f) {
return foldIn(Double.doubleToLongBits(f));
}
// --------------------
// Arrays
/**
* Augment the current computed hash code with the
* value array.
*
* @param array value being added
* @return the new hash code.
*/
public int addValue(Object[] array) {
int val = hashCode();
for (Object obj : array) {
val = addValue(obj);
}
return val;
}
/**
* Augment the current computed hash code with the
* value array.
*
* @param array value being added
* @return the new hash code.
*/
public int addValue(boolean[] array) {
int val = hashCode();
for (boolean b : array) {
val = addValue(b);
}
return val;
}
/**
* Augment the current computed hash code with the
* value i.
*
* @param array value being added
* @return the new hash code.
*/
public int addValue(byte[] array) {
int val = hashCode();
for (byte i : array) {
val = addValue(i);
}
return val;
}
/**
* Augment the current computed hash code with the
* value array.
*
* @param array value being added
* @return the new hash code.
*/
public int addValue(char[] array) {
int val = hashCode();
for (char i : array) {
val = addValue(i);
}
return val;
}
/**
* Augment the current computed hash code with the
* value array.
*
* @param array value being added
* @return the new hash code.
*/
public int addValue(short[] array) {
int val = hashCode();
for (short i : array) {
val = addValue(i);
}
return val;
}
/**
* Augment the current computed hash code with the
* value array.
*
* @param array value being added
* @return the new hash code.
*/
public int addValue(int[] array) {
int val = hashCode();
for (int i : array) {
val = addValue(i);
}
return val;
}
/**
* Augment the current computed hash code with the
* value array.
*
* @param array value being added
* @return the new hash code.
*/
public int addValue(float[] array) {
int val = hashCode();
for (float f : array) {
val = addValue(f);
}
return val;
}
/**
* Augment the current computed hash code with the
* value array.
*
* @param array value being added
* @return the new hash code.
*/
public int addValue(double[] array) {
int val = hashCode();
for (double f : array) {
val = addValue(f);
}
return val;
}
// --------------------
// Utility methods
/**
* Utility function to make it easy to compare two, possibly null, objects.
*
* @param o1 first object
* @param o2 second object
* @return true iff either both objects are null, or
* neither are null and they are equal.
*/
public static boolean equalObjects(Object o1, Object o2) {
if (o1 == null) {
return (o2 == null);
} else if (o2 == null) {
return false;
} else {
return o1.equals(o2);
}
}
// --------------------
// Internals
private int foldIn(int c) {
return setVal((SCALE * mVal) + c);
}
private int foldIn(long c) {
return setVal((SCALE * mVal) + c);
}
private int setVal(long l) {
mVal = (int)(l ^ (l>>>32));
return mVal;
}
// ----------------------------------------
// Generic object protocol
/**
* Get the currently computed hash code value.
*/
@Override
public int hashCode() {
return mVal;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
} else if (obj == null || obj.getClass() != getClass()) {
return false;
}
HashCode h = (HashCode)obj;
return (h.hashCode() == hashCode());
}
@Override
public String toString() {
return "{HashCode " + mVal + "}";
}
} // HashCode